using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace JavaScript.Debugger
{
public partial class DebugWindow : Form
{
protected Stack<JsInterp> m_interps = new Stack<JsInterp>();
protected Stack<ExecList> m_progs = new Stack<ExecList>();
protected JsEngine m_engine;
protected JsInterp m_interp;
protected JsObject m_returnVal;
protected ExecList m_program;
protected List<int> m_lines = new List<int>();
protected string[] m_salines;
protected ContextInspector m_inspector;
public DebugWindow( JsEngine engine, DebuggerException de )
{
InitializeComponent();
m_engine = engine;
m_interp = de.JsInterp;
SetupDisplay();
DisplayNextCommand();
}
public JsObject PushEval(JsInterp interp)
{
//m_interps.Push(m_interp);
//m_progs.Push(m_program);
//m_interp = interp;
//m_program = m_interp.DebugGetCurrentProg();
//SetupDisplay();
DebugWindow dw = new DebugWindow(m_engine, new DebuggerException(interp));
dw.ShowDialog();
JsObject ret = dw.ReturnValue;
dw.Dispose();
return ret;
}
public void EndSession()
{
Hide();
if (null != m_inspector)
{
m_inspector.Hide();
m_inspector.Dispose();
m_inspector = null;
}
Dispose();
}
public JsObject ReturnValue
{
get
{
return m_returnVal;
}
}
private void SetupDisplay()
{
m_returnVal = null;
rtbCode.Focus();
lstAsm.Items.Clear();
m_program = m_interp.DebugGetCurrentProg();
for (int x = 0; x < m_program.Count; x++)
{
Command cmd = (Command)m_program[x];
lstAsm.Items.Add(x + "> " + cmd.ToString());
}
string src = m_program.SourceCode;
rtbCode.Clear();
rtbCode.Text = src;
rtbCode.SelectionBackColor = Color.Red;
rtbCode.ReadOnly = true;
m_lines.Clear();
m_salines = src.Split(new char[] { '\n' }, StringSplitOptions.None);
int chpos = 0;
m_lines.Add(0);
for (int x = 0; x < m_salines.Length; x++)
{
chpos += m_salines[x].Length;
m_lines.Add(chpos);
}
Debug.Assert(m_salines.Length+1 == m_lines.Count);
SetupStacks();
}
private void SetupStacks()
{
if (lstContext.Items.Count != m_interp.Context.Count)
{
lstContext.Items.Clear();
StackFrame ctx = m_interp.Context;
object[] ctxitms = ctx.ToArray();
for (int x = 0; x < ctx.Count; x++)
{
lstContext.Items.Add(ctxitms[x]);
}
}
lstStack.Items.Clear();
Stack<object> stk = m_interp.DebugGetStack();
object[] stkitms = stk.ToArray();
for (int x = 0; x < stkitms.Length; x++)
{
lstStack.Items.Add(stkitms[x]);
}
}
private void DisplayNextCommand()
{
if (m_program != m_interp.DebugGetCurrentProg())
{
SetupDisplay();
}
lstAsm.SelectedIndex = m_interp.DebugGetCurrentPC();
int line = m_interp.DebugGetCurrentCommand().LineNumber-1;
if (line < 0)
{
line = 0;
}
if (line < m_lines.Count)
{
rtbCode.Select((line >= m_lines.Count) ? m_lines[line - 1] : m_lines[line], (line >= m_salines.Length) ? m_salines[m_salines.Length - 1].Length : m_salines[line].Length);
}
if (null != m_inspector)
{
m_inspector.DebuggerStepped();
}
}
private void btnStep_Click(object sender, EventArgs e)
{
try
{
if (!m_interp.EOF && m_interp.Step())
{
if (m_interps.Count > 0)
{
m_interp = m_interps.Pop();
m_program = m_progs.Pop();
SetupDisplay();
}
else
{
m_returnVal = m_interp.ReturnValue();
Debug.Assert(null != m_returnVal);
Hide();
if (null != m_inspector)
{
m_inspector.Hide();
m_inspector.Dispose();
m_inspector = null;
}
return;
}
}
if (!m_interp.EOF && m_interp.DebugGetCurrentCommand().OpCode == Op.NATIVE)
{
m_interp.Step();
m_interp.Step();
}
DisplayNextCommand();
SetupStacks();
}
catch (EndCurrentProgramException)
{
m_interp.DebugGetCurrentProg().EOF = true;
}
}
private void btnRun_Click(object sender, EventArgs e)
{
while (m_returnVal == null)
{
btnStep_Click(null, null);
System.Threading.Thread.Sleep(1);
}
}
private void btnStepOut_Click(object sender, EventArgs e)
{
ExecList prog = m_program;
while (prog == m_program && !m_interp.EOF)
{
btnStep_Click(null, null);
System.Threading.Thread.Sleep(1);
}
}
private void btnContextInspector_Click(object sender, EventArgs e)
{
if (null == m_inspector)
{
m_inspector = new ContextInspector(this, m_interp.Context.OuterContext);
m_inspector.Show();
m_inspector.Left = this.Left + this.Size.Width;
m_inspector.Top = this.Top;
}
else
{
m_inspector.Hide();
m_inspector.Dispose();
m_inspector = null;
}
}
private void DebugWindow_Shown(object sender, EventArgs e)
{
this.Left = 0;
}
public void DebugWindow_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F11)
{
if (e.Shift)
{
btnStepOut_Click(null, null);
}
else
{
btnStep_Click(null, null);
}
}
else if (e.KeyCode == Keys.F5)
{
btnRun_Click(null, null);
}
}
private void DebugWindow_FormClosed(object sender, FormClosedEventArgs e)
{
if (null != m_inspector)
{
m_inspector.Hide();
m_inspector.Dispose();
m_inspector = null;
}
}
private void btnEval_Click(object sender, EventArgs e)
{
Evaluator ev = new Evaluator(m_engine, m_interp.Context.OuterContext);
ev.ShowDialog();
ev.Dispose();
ev = null;
}
}
}