/////////////////////////////////////////////////////////////////////// internal StringList GetLocals( Interpreter interpreter, string pattern ) { if (pattern != null) { pattern = ScriptOps.MakeVariableName(pattern); } StringList result = new StringList(); foreach (KeyValuePair <string, IVariable> pair in this) { IVariable variable = pair.Value; if (variable == null) { continue; } if (EntityOps.IsUndefined(variable) || EntityOps.IsLink(variable)) { continue; } ICallFrame frame = CallFrameOps.FollowNext(variable.Frame); if (interpreter != null) { if (interpreter.IsGlobalCallFrame(frame)) { continue; } if (Interpreter.IsNamespaceCallFrame(frame)) { continue; } } string name = variable.Name; if ((pattern == null) || StringOps.Match( interpreter, StringOps.DefaultMatchMode, name, pattern, false)) { result.Add(name); } } return(result); }
/////////////////////////////////////////////////////////////////////// #region INotify Members public override ReturnCode Notify( Interpreter interpreter, IScriptEventArgs eventArgs, IClientData clientData, ArgumentList arguments, ref Result result ) { if (eventArgs == null) { return(ReturnCode.Ok); } if (!FlagOps.HasFlags( eventArgs.NotifyTypes, NotifyType.CallFrame, false)) { return(ReturnCode.Ok); } NotifyFlags notifyFlags = eventArgs.NotifyFlags; if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Popped | NotifyFlags.Deleted, false)) { return(ReturnCode.Ok); } IClientData eventClientData = eventArgs.ClientData; if (eventClientData == null) { return(ReturnCode.Ok); } ICallFrame newFrame = eventClientData.Data as ICallFrame; if (newFrame == null) { return(ReturnCode.Ok); } // // NOTE: Make sure the variables in this frame actually BELONG // to this frame. Also, we do not handle the global call // frame. // if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Force, true) && !CallFrameOps.IsNonGlobalVariable(newFrame)) { return(ReturnCode.Ok); } // // NOTE: If this is a [scope] created call frame, we do NOT want // to change any reference counts unless the call frame is // being deleted, not simply popped. // if (!FlagOps.HasFlags(notifyFlags, NotifyFlags.Deleted, true) && CallFrameOps.IsScope(newFrame)) { return(ReturnCode.Ok); } // // NOTE: Grab the variables for this call frame. If there are // none, we are done. // VariableDictionary variables = newFrame.Variables; if (variables == null) { return(ReturnCode.Ok); } // // NOTE: Process each variable in the call frame to adjust all // all the reference counts. After this point, we need // the interpreter context for the event. // Interpreter eventInterpreter = eventArgs.Interpreter; if (eventInterpreter == null) { return(ReturnCode.Ok); } foreach (KeyValuePair <string, IVariable> pair in variables) { // // NOTE: Grab the variable and make sure the variable it is // valid. // IVariable variable = pair.Value; if (variable == null) { continue; } // // NOTE: For unset operations, ObjectTraceCallback uses only // the "traceInfo.Variable" and "traceInfo.oldValue" // members of the ITraceInfo object instance. If the // number of trace and/or watch levels exceeds one, // force creation of a new TraceInfo object here; // otherwise, we may interfere with the setting of an // unrelated variable value. // ITraceInfo traceInfo = ScriptOps.NewTraceInfo( interpreter, null, BreakpointType.BeforeVariableUnset, newFrame, variable, pair.Key, null, VariableFlags.None, variable.Value, null, null, null, null, interpreter.NeedNewTraceInfo(VariableFlags.None), false, !EntityOps.IsNoPostProcess(variable), ReturnCode.Ok); // // HACK: Manually invoke the Interpreter.ObjectTraceCallback // static (trace callback) method, in order to handle // contained object reference(s), if any. After this // method returns, the entire call frame will be going // away, along with any object references contained // within it. // ReturnCode code = Interpreter.ObjectTraceCallback( traceInfo.BreakpointType, eventInterpreter, traceInfo, ref result); if (code != ReturnCode.Ok) { return(code); } } return(ReturnCode.Ok); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"uplevel ?level? arg ?arg ...?\""; return(ReturnCode.Error); } ReturnCode code; int currentLevel = 0; code = interpreter.GetInfoLevel( CallFrameOps.InfoLevelSubCommand, ref currentLevel, ref result); if (code != ReturnCode.Ok) { return(code); } bool mark = false; bool absolute = false; bool super = false; int level = 0; ICallFrame currentFrame = null; ICallFrame otherFrame = null; FrameResult frameResult = interpreter.GetCallFrame( arguments[1], ref mark, ref absolute, ref super, ref level, ref currentFrame, ref otherFrame, ref result); if (frameResult == FrameResult.Invalid) { return(ReturnCode.Error); } int argumentIndex = ((int)frameResult + 1); // // BUGFIX: The argument count needs to be checked again here. // if (argumentIndex >= arguments.Count) { result = "wrong # args: should be \"uplevel ?level? arg ?arg ...?\""; return(ReturnCode.Error); } if (mark) { code = CallFrameOps.MarkMatching( interpreter.CallStack, interpreter.CurrentFrame, absolute, level, CallFrameFlags.Variables, CallFrameFlags.Invisible | CallFrameFlags.NoVariables, CallFrameFlags.Invisible, false, false, true, ref result); } if (code == ReturnCode.Ok) { try { string name = StringList.MakeList("uplevel", arguments[1]); ICallFrame newFrame = interpreter.NewUplevelCallFrame( name, currentLevel, CallFrameFlags.None, mark, currentFrame, otherFrame); ICallFrame savedFrame = null; interpreter.PushUplevelCallFrame( currentFrame, newFrame, true, ref savedFrame); if ((argumentIndex + 1) >= arguments.Count) { code = interpreter.EvaluateScript( arguments[argumentIndex], ref result); } else { code = interpreter.EvaluateScript( arguments, argumentIndex, ref result); } if (code == ReturnCode.Error) { Engine.AddErrorInformation(interpreter, result, String.Format("{0} (\"uplevel\" body line {1})", Environment.NewLine, Interpreter.GetErrorLine(interpreter))); } // // NOTE: Pop the original call frame that we pushed above and // any intervening scope call frames that may be leftover // (i.e. they were not explicitly closed). // /* IGNORED */ interpreter.PopUplevelCallFrame( currentFrame, newFrame, ref savedFrame); } finally { if (mark) { // // NOTE: We should not get an error at this point from // unmarking the call frames; however, if we do get // one, we need to complain loudly about it because // that means the interpreter state has probably been // corrupted somehow. // ReturnCode markCode; Result markResult = null; markCode = CallFrameOps.MarkMatching( interpreter.CallStack, interpreter.CurrentFrame, absolute, level, CallFrameFlags.Variables, CallFrameFlags.NoVariables, CallFrameFlags.Invisible, false, false, false, ref markResult); if (markCode != ReturnCode.Ok) { DebugOps.Complain(interpreter, markCode, markResult); } } } } return(code); }
/////////////////////////////////////////////////////////////////////// #region IExecute Members public override ReturnCode Execute( Interpreter interpreter, IClientData clientData, ArgumentList arguments, ref Result result ) { if (interpreter == null) { result = "invalid interpreter"; return(ReturnCode.Error); } if (arguments == null) { result = "invalid argument list"; return(ReturnCode.Error); } if (arguments.Count < 2) { result = "wrong # args: should be \"variable ?name value...? name ?value?\""; return(ReturnCode.Error); } ICallFrame localFrame = null; if (interpreter.GetVariableFrameViaResolvers( LookupFlags.Default, ref localFrame, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } if (localFrame == null) { result = "local call frame is invalid"; return(ReturnCode.Error); } if (!localFrame.IsVariable) { result = "local call frame does not support variables"; return(ReturnCode.Error); } bool useNamespaces = interpreter.AreNamespacesEnabled(); INamespace currentNamespace = null; if (useNamespaces && interpreter.GetCurrentNamespaceViaResolvers( null, LookupFlags.Default, ref currentNamespace, ref result) != ReturnCode.Ok) { return(ReturnCode.Error); } ICallFrame otherFrame = null; if ((currentNamespace != null) && !interpreter.IsGlobalNamespace(currentNamespace)) { otherFrame = currentNamespace.VariableFrame; } else { otherFrame = interpreter.CurrentGlobalFrame; } for (int argumentIndex = 1; argumentIndex < arguments.Count; argumentIndex += 2) { string varName = arguments[argumentIndex]; lock (interpreter.SyncRoot) /* TRANSACTIONAL */ { VariableFlags flags = VariableFlags.NoElement; if (!useNamespaces) { flags |= VariableFlags.GlobalOnly; } IVariable otherVariable = null; Result error = null; if (interpreter.GetVariableViaResolversWithSplit( varName, ref flags, ref otherVariable, ref error) != ReturnCode.Ok) { if (FlagOps.HasFlags( flags, VariableFlags.NotFound, true)) { error = null; if (interpreter.AddVariable2( VariableFlags.Undefined | flags, varName, null, true, ref otherVariable, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } else { // // NOTE: We did not search for the variable, let // the caller know why. // result = error; return(ReturnCode.Error); } } // // NOTE: Create the variable link between the local frame // (i.e. a procedure, etc) and the other frame (i.e. // namespace or global). // if (CallFrameOps.IsLocal(localFrame)) { error = null; if (ScriptOps.LinkVariable( interpreter, localFrame, varName, otherFrame, varName, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } // // NOTE: If they provided a value, set it now. // // BUGFIX: This must be done after setting up the link // and not before; otherwise, the LinkVariable // method will detect a defined variable with // the same name in the local call frame and // refuse to overwrite it (by design). // if ((argumentIndex + 1) < arguments.Count) { error = null; if (interpreter.SetVariableValue2( VariableFlags.None, otherFrame, varName, null, arguments[argumentIndex + 1].Value, null, ref otherVariable, ref error) != ReturnCode.Ok) { result = error; return(ReturnCode.Error); } } } } result = String.Empty; return(ReturnCode.Ok); }