Fix parsing bug; Extend GUI
This commit is contained in:
parent
6cb84a664a
commit
9a35dc5ec9
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -89,6 +89,15 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.5"
|
||||
@ -560,6 +569,7 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
name = "dust-lang"
|
||||
version = "0.4.0"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"cc",
|
||||
"clap",
|
||||
"csv",
|
||||
|
@ -35,6 +35,7 @@ eframe = { version = "0.24.1", default-features = false, features = [
|
||||
"glow", # Use the glow rendering backend. Alternative: "wgpu".
|
||||
"persistence", # Enable restoring app state when restarting the app.
|
||||
] }
|
||||
ansi_term = "0.12.1"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
env_logger = "0.10"
|
||||
|
@ -1,28 +1,50 @@
|
||||
use dust_lang::{interpret, Result, Value};
|
||||
use std::{fs::read_to_string, path::PathBuf};
|
||||
|
||||
use dust_lang::{Interpreter, Map, Result, Value};
|
||||
use egui::{Align, Layout};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct App {
|
||||
path: String,
|
||||
source: String,
|
||||
context: Map,
|
||||
#[serde(skip)]
|
||||
interpreter: Interpreter,
|
||||
output: Result<Value>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new(cc: &eframe::CreationContext<'_>, source: String) -> Self {
|
||||
// This is also where you can customize the look and feel of egui using
|
||||
// `cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
|
||||
|
||||
cc.egui_ctx.set_zoom_factor(1.5);
|
||||
|
||||
let app = App {
|
||||
source,
|
||||
output: Ok(Value::default()),
|
||||
};
|
||||
|
||||
if let Some(storage) = cc.storage {
|
||||
return eframe::get_value(storage, eframe::APP_KEY).unwrap_or(app);
|
||||
pub fn new(cc: &eframe::CreationContext<'_>, path: PathBuf) -> Self {
|
||||
fn create_app(path: PathBuf) -> App {
|
||||
let context = Map::new();
|
||||
let mut interpreter = Interpreter::new(context.clone());
|
||||
let read_source = read_to_string(&path);
|
||||
let source = if let Ok(source) = read_source {
|
||||
source
|
||||
} else {
|
||||
app
|
||||
String::new()
|
||||
};
|
||||
let output = interpreter.run(&source);
|
||||
|
||||
App {
|
||||
path: path.to_string_lossy().to_string(),
|
||||
source,
|
||||
context,
|
||||
interpreter,
|
||||
output,
|
||||
}
|
||||
}
|
||||
|
||||
if path.is_file() {
|
||||
create_app(path)
|
||||
} else {
|
||||
if let Some(storage) = cc.storage {
|
||||
return eframe::get_value(storage, eframe::APP_KEY)
|
||||
.unwrap_or_else(|| create_app(path));
|
||||
} else {
|
||||
create_app(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,17 +65,30 @@ impl eframe::App for App {
|
||||
ui.add_space(16.0);
|
||||
|
||||
egui::widgets::global_dark_light_mode_buttons(ui);
|
||||
|
||||
ui.with_layout(Layout::right_to_left(Align::Max), |ui| {
|
||||
egui::warn_if_debug_build(ui);
|
||||
ui.hyperlink_to("source code", "https://git.jeffa.io/jeff/dust");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
ui.code_editor(&mut self.source);
|
||||
ui.with_layout(Layout::left_to_right(Align::Min), |ui| {
|
||||
ui.with_layout(Layout::top_down(Align::Min).with_main_justify(true), |ui| {
|
||||
ui.with_layout(Layout::left_to_right(Align::Min), |ui| {
|
||||
ui.text_edit_singleline(&mut self.path);
|
||||
|
||||
if ui.button("run").clicked() {
|
||||
self.output = interpret(&self.source);
|
||||
if ui.button("read").clicked() {
|
||||
self.source = read_to_string(&self.path).unwrap();
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
if ui.button("run").clicked() {
|
||||
self.output = self.interpreter.run(&self.source);
|
||||
}
|
||||
});
|
||||
ui.code_editor(&mut self.source);
|
||||
});
|
||||
|
||||
let output_text = match &self.output {
|
||||
Ok(value) => value.to_string(),
|
||||
@ -61,10 +96,6 @@ impl eframe::App for App {
|
||||
};
|
||||
|
||||
ui.label(output_text);
|
||||
|
||||
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| {
|
||||
egui::warn_if_debug_build(ui);
|
||||
ui.hyperlink_to("source code", "https://git.jeffa.io/jeff/dust");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use std::{fs::read_to_string, path::PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
@ -9,14 +9,17 @@ mod app;
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
// Path to the file to read.
|
||||
path: PathBuf,
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() -> eframe::Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let path = Args::parse().path;
|
||||
let source = read_to_string(&path).unwrap();
|
||||
let path = if let Some(path) = Args::parse().path {
|
||||
path
|
||||
} else {
|
||||
PathBuf::new()
|
||||
};
|
||||
let native_options = eframe::NativeOptions {
|
||||
viewport: egui::ViewportBuilder::default()
|
||||
.with_inner_size([400.0, 300.0])
|
||||
@ -27,6 +30,6 @@ fn main() -> eframe::Result<()> {
|
||||
eframe::run_native(
|
||||
"Dust GUI",
|
||||
native_options,
|
||||
Box::new(|cc| Box::new(app::App::new(cc, source))),
|
||||
Box::new(|cc| Box::new(app::App::new(cc, path))),
|
||||
)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ pub fn interpret(source: &str) -> Result<Value> {
|
||||
/// );
|
||||
/// ```
|
||||
pub fn interpret_with_context(source: &str, context: Map) -> Result<Value> {
|
||||
let mut interpreter = Interpreter::new(context)?;
|
||||
let mut interpreter = Interpreter::new(context);
|
||||
let value = interpreter.run(source)?;
|
||||
|
||||
Ok(value)
|
||||
@ -56,25 +56,27 @@ pub struct Interpreter {
|
||||
}
|
||||
|
||||
impl Interpreter {
|
||||
pub fn new(context: Map) -> Result<Self> {
|
||||
pub fn new(context: Map) -> Self {
|
||||
let mut parser = Parser::new();
|
||||
|
||||
parser.set_language(language())?;
|
||||
parser
|
||||
.set_language(language())
|
||||
.expect("Language version is incompatible with tree sitter version.");
|
||||
|
||||
Ok(Interpreter {
|
||||
Interpreter {
|
||||
parser,
|
||||
context,
|
||||
syntax_tree: None,
|
||||
abstract_tree: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_only(&mut self, source: &str) {
|
||||
self.syntax_tree = self.parser.parse(source, self.syntax_tree.as_ref());
|
||||
self.syntax_tree = self.parser.parse(source, None);
|
||||
}
|
||||
|
||||
pub fn run(&mut self, source: &str) -> Result<Value> {
|
||||
self.syntax_tree = self.parser.parse(source, self.syntax_tree.as_ref());
|
||||
self.syntax_tree = self.parser.parse(source, None);
|
||||
self.abstract_tree = if let Some(syntax_tree) = &self.syntax_tree {
|
||||
Some(Root::from_syntax_node(
|
||||
source,
|
||||
@ -100,3 +102,9 @@ impl Interpreter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Interpreter {
|
||||
fn default() -> Self {
|
||||
Interpreter::new(Map::new())
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ fn main() {
|
||||
let mut parser = TSParser::new();
|
||||
parser.set_language(language()).unwrap();
|
||||
|
||||
let mut interpreter = Interpreter::new(context).unwrap();
|
||||
let mut interpreter = Interpreter::new(context);
|
||||
|
||||
if args.show_syntax_tree {
|
||||
interpreter.parse_only(&source);
|
||||
|
@ -154,7 +154,7 @@ mod value {
|
||||
let function = value.as_function().unwrap();
|
||||
|
||||
assert_eq!(&Vec::<Identifier>::with_capacity(0), function.parameters());
|
||||
assert_eq!(Ok(&Type::Integer), function.return_type());
|
||||
assert_eq!(&Type::Integer, function.return_type());
|
||||
|
||||
let result = interpret("(x <bool>) -> <bool> {true}");
|
||||
let value = result.unwrap();
|
||||
@ -164,7 +164,7 @@ mod value {
|
||||
&vec![Identifier::new("x".to_string())],
|
||||
function.parameters()
|
||||
);
|
||||
assert_eq!(Ok(&Type::Boolean), function.return_type());
|
||||
assert_eq!(&Type::Boolean, function.return_type());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Loading…
Reference in New Issue
Block a user