Add egui_extras dependency
Adds `egui_extras` to Cargo.toml and Cargo.lock to enable enhanced table widgets. Also introduces a new `StateTab` enum and integrates the `egui_extras::TableBuilder` to display global variables in a structured table within the application's state panel. This enhances the debugging and introspection capabilities of the compiler UI by providing a clear view of the environment's global state.
This commit is contained in:
Generated
+124
@@ -1199,6 +1199,20 @@ dependencies = [
|
||||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "egui_extras"
|
||||
version = "0.33.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d01d34e845f01c62e3fded726961092e70417d66570c499b9817ab24674ca4ed"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"egui",
|
||||
"enum-map",
|
||||
"log",
|
||||
"mime_guess2",
|
||||
"profiling",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "egui_glow"
|
||||
version = "0.33.3"
|
||||
@@ -1237,6 +1251,26 @@ version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
|
||||
|
||||
[[package]]
|
||||
name = "enum-map"
|
||||
version = "2.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
|
||||
dependencies = [
|
||||
"enum-map-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-map-derive"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.7.12"
|
||||
@@ -2179,6 +2213,24 @@ dependencies = [
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess2"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1706dc14a2e140dec0a7a07109d9a3d5890b81e85bd6c60b906b249a77adf0ca"
|
||||
dependencies = [
|
||||
"mime",
|
||||
"phf",
|
||||
"phf_shared",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
@@ -2206,6 +2258,7 @@ dependencies = [
|
||||
"chrono",
|
||||
"clap",
|
||||
"eframe",
|
||||
"egui_extras",
|
||||
"fastrand",
|
||||
"insta",
|
||||
"regex",
|
||||
@@ -2703,6 +2756,50 @@ version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
|
||||
dependencies = [
|
||||
"phf_macros",
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
@@ -2883,6 +2980,21 @@ version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "range-alloc"
|
||||
version = "0.1.4"
|
||||
@@ -3226,6 +3338,12 @@ version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
@@ -3639,6 +3757,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
|
||||
@@ -6,6 +6,7 @@ default-run = "myc"
|
||||
|
||||
[dependencies]
|
||||
eframe = "0.33.3"
|
||||
egui_extras = "0.33"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
chrono = "0.4"
|
||||
regex = "1.10"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
(fn [eu ge]
|
||||
(do
|
||||
(def dax (.close (ge 0)))
|
||||
(def eur (- dax (ge 1)))
|
||||
(def eur (- dax (.close (ge 1))))
|
||||
(print cnt ": dax=" eur " (" (/ eur (.close (eu 0))) "$)" )
|
||||
(assign cnt (+ cnt 1))
|
||||
)
|
||||
|
||||
@@ -587,6 +587,41 @@ impl Environment {
|
||||
}
|
||||
|
||||
|
||||
/// Returns all user-defined global bindings with their name, type and current value.
|
||||
///
|
||||
/// Iterates over the user scopes (index 1+), skipping the frozen RTL scope.
|
||||
/// Root-level bindings use `Address::Local(VirtualId)` in the scope map —
|
||||
/// the Local→Global translation only happens at resolve time in the binder,
|
||||
/// so we treat Local slots as global indices here.
|
||||
pub fn list_user_globals(&self) -> Vec<(String, StaticType, Value)> {
|
||||
let scopes = self.root_scopes.borrow();
|
||||
let types = self.root_types.borrow();
|
||||
let user_vals = self.user_values.borrow();
|
||||
let rtl_slot_count = self.rtl.slot_count as usize;
|
||||
|
||||
let mut result = Vec::new();
|
||||
|
||||
for scope in scopes.iter().skip(1) {
|
||||
for (sym, info) in &scope.locals {
|
||||
let slot = match info.addr {
|
||||
Address::Global(idx) => idx.0 as usize,
|
||||
Address::Local(vid) => vid.0 as usize,
|
||||
Address::Upvalue(_) => continue,
|
||||
};
|
||||
|
||||
if slot >= rtl_slot_count {
|
||||
let user_idx = slot - rtl_slot_count;
|
||||
let ty = types.get(slot).cloned().unwrap_or(StaticType::Any);
|
||||
let val = user_vals.get(user_idx).cloned().unwrap_or(Value::Void);
|
||||
result.push((sym.name.to_string(), ty, val));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
result
|
||||
}
|
||||
|
||||
/// Returns the names of all bindings registered in the fixed RTL scope.
|
||||
/// Useful for introspection (e.g., MCP server listing available built-ins).
|
||||
pub fn list_bindings(&self) -> Vec<String> {
|
||||
|
||||
+79
@@ -1,4 +1,5 @@
|
||||
use eframe::egui;
|
||||
use egui_extras::{Column, TableBuilder};
|
||||
use myc::ast::compiler::emitter;
|
||||
use myc::ast::environment::Environment;
|
||||
use myc::ast::parser::Parser;
|
||||
@@ -29,6 +30,13 @@ enum AppTab {
|
||||
Trace,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum StateTab {
|
||||
Globals,
|
||||
Dataflow,
|
||||
Series,
|
||||
}
|
||||
|
||||
struct CompilerApp {
|
||||
source_code: String,
|
||||
current_example_path: Option<PathBuf>,
|
||||
@@ -38,6 +46,7 @@ struct CompilerApp {
|
||||
trace_logs: Vec<String>,
|
||||
active_tab: AppTab,
|
||||
debug_enabled: bool,
|
||||
state_tab: StateTab,
|
||||
env: Environment,
|
||||
is_first_frame: bool,
|
||||
examples: Vec<Example>,
|
||||
@@ -86,6 +95,7 @@ impl Default for CompilerApp {
|
||||
trace_logs: Vec::new(),
|
||||
active_tab: AppTab::Output,
|
||||
debug_enabled: false,
|
||||
state_tab: StateTab::Globals,
|
||||
env,
|
||||
is_first_frame: true,
|
||||
examples,
|
||||
@@ -573,6 +583,75 @@ impl eframe::App for CompilerApp {
|
||||
}
|
||||
});
|
||||
|
||||
// Right Side Panel: Environment State Inspector
|
||||
egui::SidePanel::right("state_panel")
|
||||
.resizable(true)
|
||||
.default_width(300.0)
|
||||
.min_width(200.0)
|
||||
.show(ctx, |ui| {
|
||||
ui.horizontal(|ui| {
|
||||
ui.selectable_value(&mut self.state_tab, StateTab::Globals, "Globals");
|
||||
ui.selectable_value(&mut self.state_tab, StateTab::Dataflow, "Dataflow");
|
||||
ui.selectable_value(&mut self.state_tab, StateTab::Series, "Series");
|
||||
});
|
||||
ui.separator();
|
||||
|
||||
match self.state_tab {
|
||||
StateTab::Globals => {
|
||||
let globals = self.env.list_user_globals();
|
||||
let scopes = self.env.root_scopes.borrow();
|
||||
let rtl_slots = self.env.rtl.slot_count;
|
||||
let total_slots = *self.env.root_slot_count.borrow();
|
||||
let scope_details: Vec<String> = scopes.iter().enumerate().map(|(i, s)| {
|
||||
let entries: Vec<String> = s.locals.iter().map(|(sym, info)| {
|
||||
format!("{}={:?}", sym.name, info.addr)
|
||||
}).collect();
|
||||
format!("S{}[{}]", i, entries.join(", "))
|
||||
}).collect();
|
||||
drop(scopes);
|
||||
ui.label(format!(
|
||||
"DEBUG: rtl={}, total={}, found={}", rtl_slots, total_slots, globals.len()
|
||||
));
|
||||
for s in &scope_details {
|
||||
ui.label(s);
|
||||
}
|
||||
if globals.is_empty() {
|
||||
ui.label("No user globals. Run a script first.");
|
||||
} else {
|
||||
let available = ui.available_height();
|
||||
TableBuilder::new(ui)
|
||||
.striped(true)
|
||||
.resizable(true)
|
||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||
.min_scrolled_height(available)
|
||||
.column(Column::auto().at_least(60.0))
|
||||
.column(Column::auto().at_least(60.0))
|
||||
.column(Column::remainder().at_least(80.0))
|
||||
.header(18.0, |mut header| {
|
||||
header.col(|ui| { ui.strong("Name"); });
|
||||
header.col(|ui| { ui.strong("Type"); });
|
||||
header.col(|ui| { ui.strong("Value"); });
|
||||
})
|
||||
.body(|mut body| {
|
||||
for (name, ty, val) in &globals {
|
||||
body.row(18.0, |mut row| {
|
||||
row.col(|ui| { ui.monospace(name); });
|
||||
row.col(|ui| { ui.monospace(ty.to_string()); });
|
||||
row.col(|ui| { ui.monospace(val.to_string()); });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
StateTab::Dataflow => {
|
||||
ui.label("Stream/Pipe dataflow graph will appear here after execution.");
|
||||
}
|
||||
StateTab::Series => {
|
||||
ui.label("Series contents will appear here after execution.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Central Panel: Source Code Editor (Fills remaining space)
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.heading("Source Code Editor");
|
||||
|
||||
Reference in New Issue
Block a user