Skip to content

Commit

Permalink
Cider Dap - Variables displaying (#2357)
Browse files Browse the repository at this point in the history
bad branch name (oops)
This branch adds the following functionality to the VSCode Cider
debugger:

1. Displaying accurate port values
2. Continue requests now behave according to the spec by informing
VSCode why the debugger was stopped
3. Cells (scopes) displayed now only shows the cells for the current
component, rather then every cell in the environment
4. Small json tweaks (name, publisher, etc)

---------

Co-authored-by: Serena <[email protected]>
  • Loading branch information
smd21 and Serena authored Dec 11, 2024
1 parent 260d2f1 commit 3057347
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 132 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion cider-dap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dap = { git = "https://github.com/sztomi/dap-rs", tag = "v0.3.1-alpha1" }
dap = { git = "https://github.com/sztomi/dap-rs", tag = "v0.4.1-alpha1" }
thiserror = "1.*"
serde_json = "1.0"
serde.workspace= true
Expand All @@ -15,6 +15,7 @@ argh = "0.1"
slog = "2.7.0"
slog-term = "2.8.0"
slog-async = "2.7.0"
baa = "0.14"

interp = { path = "../interp" }

Expand Down
4 changes: 2 additions & 2 deletions cider-dap/calyxDebug/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "cider-dap",
"displayName": "Cider",
"displayName": "Cider DAP",
"version": "0.0.1",
"publisher": "Cider",
"publisher": "Capra @ Cornell",
"description": "A debug adapter for Calyx files",
"author": {
"name": "...",
Expand Down
172 changes: 121 additions & 51 deletions cider-dap/src/adapter.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
use crate::error::AdapterResult;
use baa::BitVecOps;
use dap::events::{Event, OutputEventBody, StoppedEventBody};
use dap::types::{
Breakpoint, Scope, Source, SourceBreakpoint, StackFrame, Thread, Variable,
self, Breakpoint, Scope, Source, SourceBreakpoint, StackFrame, Thread,
Variable,
};
use interp::debugger::commands::ParsedGroupName;
use interp::debugger::source::structures::NewSourceMap;
use interp::debugger::OwnedDebugger;
use interp::debugger::{OwnedDebugger, StoppedReason};
use interp::flatten::flat_ir::base::{GlobalCellIdx, PortValue};
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;

pub struct MyAdapter {
#[allow(dead_code)]
debugger: OwnedDebugger,
break_count: Counter,
_break_count: Counter,
thread_count: Counter,
stack_count: Counter,
breakpoints: HashSet<i64>,
stack_frames: Vec<StackFrame>, // This field is a placeholder
threads: Vec<Thread>, // This field is a placeholder
object_references: HashMap<i64, Vec<String>>,
stack_frames: Vec<StackFrame>,
threads: Vec<Thread>, // This field is a placeholder
object_references: HashMap<i64, Vec<(String, PortValue)>>,
source: String,
ids: NewSourceMap,
frames_to_cmpts: HashMap<i64, GlobalCellIdx>, //stores mapping from frame ids to component idx
}

impl MyAdapter {
Expand All @@ -28,7 +33,7 @@ impl MyAdapter {
OwnedDebugger::from_file(&PathBuf::from(path), &std_path).unwrap();
Ok(MyAdapter {
debugger,
break_count: Counter::new(),
_break_count: Counter::new(),
thread_count: Counter::new(),
stack_count: Counter::new(),
breakpoints: HashSet::new(),
Expand All @@ -37,6 +42,7 @@ impl MyAdapter {
object_references: HashMap::new(),
source: path.to_string(),
ids: metadata,
frames_to_cmpts: HashMap::new(),
})
}
/// function to deal with setting breakpoints and updating debugger accordingly
Expand Down Expand Up @@ -76,7 +82,7 @@ impl MyAdapter {
let name = self.ids.lookup_line(source_point.line as u64);

let breakpoint = make_breakpoint(
self.break_count.increment().into(),
Some(source_point.line),
name.is_some(),
Some(path.clone()),
Some(source_point.line),
Expand Down Expand Up @@ -115,7 +121,7 @@ impl MyAdapter {
self.debugger.delete_breakpoints(to_debugger);
}

///Creates a thread using the parameter name.
/// Creates a thread using the parameter name.
pub fn create_thread(&mut self, name: String) -> Thread {
//how do we attach the thread to the program
let thread = Thread {
Expand All @@ -131,38 +137,46 @@ impl MyAdapter {
self.threads.clone()
}

//Returns a dummy stack frame, set to change.
pub fn create_stack(&mut self) -> Vec<StackFrame> {
let frame = StackFrame {
id: self.stack_count.increment(),
// Maybe automate the name in the future?
name: String::from("Frame"),
source: Some(Source {
name: None,
path: Some(self.source.clone()),
source_reference: None,
presentation_hint: None,
origin: None,
sources: None,
adapter_data: None,
checksums: None,
}),
line: 1,
column: 0,
end_line: None,
end_column: None,
can_restart: None,
instruction_pointer_reference: None,
module_id: None,
presentation_hint: None,
};
self.stack_frames.push(frame);
// Return all stack frames
/// returns all frames (components) in program
pub fn get_stack(&mut self) -> Vec<StackFrame> {
if self.stack_frames.is_empty() {
self.create_stack();
}
self.stack_frames.clone()
}

pub fn clone_stack(&self) -> Vec<StackFrame> {
self.stack_frames.clone()
/// creates call stack where each frame is a component. Adds frames to current
/// call stack
fn create_stack(&mut self) {
let components = self.debugger.get_components();
//turn the names into stack frames, ignore lines for right now
for (idx, comp) in components {
let frame = StackFrame {
id: self.stack_count.increment(),
// Maybe automate the name in the future?
name: String::from(comp),
source: Some(Source {
name: None,
path: Some(self.source.clone()),
source_reference: None,
presentation_hint: None,
origin: None,
sources: None,
adapter_data: None,
checksums: None,
}),
line: 1, // need to get this to be line component starts on
column: 0,
end_line: None,
end_column: None,
can_restart: None,
instruction_pointer_reference: None,
module_id: None,
presentation_hint: None,
};
self.frames_to_cmpts.insert(frame.id, idx);
self.stack_frames.push(frame);
}
}

pub fn next_line(&mut self, _thread: i64) -> bool {
Expand Down Expand Up @@ -199,26 +213,34 @@ impl MyAdapter {
Some(p) => {
let out: Vec<Variable> = p
.iter()
.map(|x| Variable {
name: String::from(x),
value: String::from("1"),
type_field: None,
presentation_hint: None,
evaluate_name: None,
variables_reference: 0,
named_variables: None,
indexed_variables: None,
memory_reference: None,
.map(|(nam, val)| {
let valu = val
.as_option()
.map(|x| x.val().to_u64().unwrap())
.unwrap_or_default();
Variable {
name: String::from(nam),
value: valu.to_string(),
type_field: None,
presentation_hint: None,
evaluate_name: None,
variables_reference: 0,
named_variables: None,
indexed_variables: None,
memory_reference: None,
}
})
.collect();
out
}
}
}
// return cells in calyx context (later should hopefully just return ones w current component)
pub fn get_scopes(&mut self, _frame: i64) -> Vec<Scope> {
// return cells in calyx context
// todo: return only cells in current stack frame (component)
pub fn get_scopes(&mut self, frame: i64) -> Vec<Scope> {
let mut out_vec = vec![];
let cell_names = self.debugger.get_cells();
let component = self.frames_to_cmpts[&frame];
let cell_names = self.debugger.get_comp_cells(component);
let mut var_ref_count = 1;
for (name, ports) in cell_names {
self.object_references.insert(var_ref_count, ports);
Expand All @@ -244,8 +266,56 @@ impl MyAdapter {
}

pub fn on_pause(&mut self) {
//self.debugger.pause();
self.object_references.clear();
}

pub fn on_continue(&mut self, thread_id: i64) -> Event {
dbg!("continue - adapter");
let result = self.debugger.cont();
match result {
// honestly not sure if this is right behavior, still unsure what an output event IS lol.
Err(e) => Event::Output(OutputEventBody {
category: Some(types::OutputEventCategory::Stderr),
output: e.to_string(),
group: Some(types::OutputEventGroup::Start),
variables_reference: None,
source: None,
line: None,
column: None,
data: None,
}),
Ok(reason) => match reason {
StoppedReason::Done => Event::Terminated(None),
StoppedReason::Breakpoint(names) => {
let bp_lines: Vec<i64> = names
.into_iter()
.map(|x| self.ids.lookup(&x).unwrap().start_line as i64)
.collect();
dbg!(&bp_lines);
//in map add adjusting stack frame lines
Event::Stopped(StoppedEventBody {
reason: types::StoppedEventReason::Breakpoint,
description: Some(String::from("hit breakpoint")),
thread_id: Some(thread_id),
preserve_focus_hint: None,
all_threads_stopped: Some(true),
text: None,
hit_breakpoint_ids: Some(bp_lines),
})
}
StoppedReason::PauseReq => Event::Stopped(StoppedEventBody {
reason: types::StoppedEventReason::Pause,
description: Some(String::from("Paused")),
thread_id: Some(thread_id),
preserve_focus_hint: None,
all_threads_stopped: Some(true),
text: None,
hit_breakpoint_ids: None,
}),
},
}
}
}

/// Simple struct used to keep an index of the breakpoints used.
Expand Down
30 changes: 6 additions & 24 deletions cider-dap/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ where
// Not sure if we need it
// Make VSCode send disassemble request
supports_stepping_granularity: Some(true),
supports_single_thread_execution_requests: Some(true),
..Default::default()
}));
server.respond(rsp)?;
Expand Down Expand Up @@ -149,23 +148,15 @@ where
// Construct the adapter
let mut adapter = MyAdapter::new(program_path, std_path)?;

// Currently, we need two threads to run the debugger and step through,
// not sure why but would be good to look into for the future.
// one thread idk why but it works
let thread = &adapter.create_thread(String::from("Main")); //does not seem as though this does anything
let thread2 = &adapter.create_thread(String::from("Thread 1"));

// Notify server of first thread
server.send_event(Event::Thread(ThreadEventBody {
reason: types::ThreadEventReason::Started,
thread_id: thread.id,
}))?;

//Notify server of second thread
server.send_event(Event::Thread(ThreadEventBody {
reason: types::ThreadEventReason::Started,
thread_id: thread2.id,
}))?;

// Return the adapter instead of running the server
Ok(adapter)
}
Expand Down Expand Up @@ -241,12 +232,7 @@ fn run_server<R: Read, W: Write>(
}
// Send StackTrace, may be useful to make it more robust in the future
Command::StackTrace(_args) => {
// Create new frame if empty, SUBJECT TO CHANGE
let frames = if adapter.clone_stack().is_empty() {
adapter.create_stack()
} else {
adapter.clone_stack()
};
let frames = adapter.get_stack();
let rsp =
req.success(ResponseBody::StackTrace(StackTraceResponse {
stack_frames: frames,
Expand All @@ -255,14 +241,16 @@ fn run_server<R: Read, W: Write>(
server.respond(rsp)?;
}
// Continue the debugger
Command::Continue(_args) => {
Command::Continue(args) => {
// need to run debugger, ngl not really sure how to implement this functionality
// run debugger until breakpoint or paused -> maybe have a process to deal w running debugger?
let stopped = adapter.on_continue(args.thread_id);
let rsp =
req.success(ResponseBody::Continue(ContinueResponse {
all_threads_continued: None,
all_threads_continued: Some(true),
}));
server.respond(rsp)?;
server.send_event(stopped)?;
}
// Send a Stopped event with reason Pause
Command::Pause(args) => {
Expand Down Expand Up @@ -347,19 +335,13 @@ fn run_server<R: Read, W: Write>(
server.send_event(stopped)?;
}
Command::Scopes(args) => {
//variables go in here most likely
//just get stuff displaying then figure out how to pretty it up

let frame_id = args.frame_id;
let rsp = req.success(ResponseBody::Scopes(ScopesResponse {
scopes: adapter.get_scopes(frame_id),
}));
info!(logger, "responded with {rsp:?}");
server.respond(rsp)?;
}
Command::Variables(args) => {
info!(logger, "variables req");
// never happening idk why
let var_ref = args.variables_reference;
let rsp =
req.success(ResponseBody::Variables(VariablesResponse {
Expand Down
Loading

0 comments on commit 3057347

Please sign in to comment.