From f0a492fc20b509d02bd341f0b4ea5afbbc306fbf Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Sat, 7 Sep 2024 10:06:51 +0800 Subject: [PATCH] create cells --- src/main.rs | 144 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 40 deletions(-) diff --git a/src/main.rs b/src/main.rs index b39aa0d..acade66 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,12 +16,16 @@ use nac3core::typecheck::{type_inferencer, typedef}; mod basic_symbol_resolver; use basic_symbol_resolver::{Resolver, ResolverInternal}; -fn run(code: &String) { +type RunFn = unsafe extern "C" fn() -> i32; + +fn compile<'a>( + context: &'a inkwell::context::Context, + code: &String, +) -> Result, String> { let llvm_options = codegen::CodeGenLLVMOptions { opt_level: inkwell::OptimizationLevel::Default, target: codegen::CodeGenTargetMachineOptions::from_host(), }; - let context = inkwell::context::Context::create(); let size_t = context .ptr_sized_int_type( &llvm_options @@ -55,8 +59,7 @@ fn run(code: &String) { match nac3parser::parser::parse_program(code.as_str(), String::from("cell1").into()) { Ok(parser_result) => parser_result, Err(err) => { - eprintln!("parse error: {}", err); - return; + return Err(format!("parse error: {}", err)); } }; for stmt in parser_result { @@ -68,8 +71,7 @@ fn run(code: &String) { } } Err(err) => { - eprintln!("composer error: {}", err); - return; + return Err(format!("composer error: {}", err)); } } } @@ -86,15 +88,15 @@ fn run(code: &String) { if let Err(errors) = composer.start_analysis(true) { let error_count = errors.len(); - eprintln!("{error_count} error(s) occurred during top level analysis."); + let mut msg = format!("{error_count} error(s) occurred during top level analysis."); for (error_i, error) in errors.iter().enumerate() { let error_num = error_i + 1; - eprintln!("=========== ERROR {error_num}/{error_count} ============"); - eprintln!("{error}"); + msg.push_str(&format!( + "\n=========== ERROR {error_num}/{error_count} ============\n{error}" + )); } - eprintln!("=================================="); - return; + return Err(msg); } let top_level = Arc::new(composer.make_top_level_context()); @@ -102,8 +104,7 @@ fn run(code: &String) { let run_id_def = match resolver.get_identifier_def("run".into()) { Ok(run_id_def) => run_id_def, Err(_) => { - eprintln!("no run() entry point"); - return; + return Err(format!("no run() entry point")); } }; let instance = { @@ -182,29 +183,54 @@ fn run(code: &String) { let execution_engine = main .create_jit_execution_engine(llvm_options.opt_level) .unwrap(); - type Run = unsafe extern "C" fn() -> i32; - let run: inkwell::execution_engine::JitFunction = - unsafe { execution_engine.get_function("run").unwrap() }; - println!("{}", unsafe { run.call() }); + return Ok(unsafe { execution_engine.get_function("run").unwrap() }); } -fn main() -> eframe::Result { - inkwell::targets::Target::initialize_all(&inkwell::targets::InitializationConfig::default()); +struct Cell<'a> { + code: String, + context: inkwell::context::Context, + result: Result, String>, +} - let options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default().with_inner_size([1024.0, 768.0]), - ..Default::default() - }; - - let mut code = String::new(); - - eframe::run_simple_native("Cells", options, move |ctx, _frame| { - let submit_key = egui::KeyboardShortcut::new(egui::Modifiers::CTRL, egui::Key::Enter); - if ctx.input_mut(|i| i.consume_shortcut(&submit_key)) { - run(&code); +impl<'a> Cell<'a> { + fn new() -> Self { + Self { + code: "".to_string(), + context: inkwell::context::Context::create(), + result: Err("".to_string()), } + } - egui::CentralPanel::default().show(ctx, |ui| { + fn update(&mut self) { + self.result = Err("borrow checker problems".to_string()) //compile(&self.context, &self.code); + } +} + +struct Cells<'a> { + cells: Vec>, +} + +impl Cells<'_> { + fn new() -> Self { + Self { + cells: vec![Cell::new()], + } + } + + fn update(&mut self) { + for cell in self.cells.iter_mut() { + cell.update() + } + } + + fn ensure_last(&mut self) { + if self.cells.last().unwrap().result.is_ok() { + self.cells.push(Cell::new()); + } + } + + fn ui(&mut self, ui: &mut egui::Ui) { + for (cell_i, cell) in self.cells.iter_mut().enumerate() { let theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx()); let mut layouter = |ui: &egui::Ui, string: &str, wrap_width: f32| { let mut layout_job = @@ -221,15 +247,53 @@ fn main() -> eframe::Result { .collect(); ui.fonts(|f| f.layout_job(layout_job)) }; - ui.add( - egui::TextEdit::multiline(&mut code) - .code_editor() - .desired_rows(4) - .lock_focus(true) - .desired_width(f32::INFINITY) - .layouter(&mut layouter) - .font(egui::FontId::monospace(16.0)), - ); + ui.group(|ui| { + ui.horizontal(|ui| { + ui.label(format!("[{}]", cell_i)); + ui.add( + egui::TextEdit::multiline(&mut cell.code) + .code_editor() + .desired_rows(4) + .lock_focus(true) + .desired_width(f32::INFINITY) + .layouter(&mut layouter) + .font(egui::FontId::monospace(16.0)), + ); + }); + match &cell.result { + Ok(run_fn) => { + ui.label(format!("{}", unsafe { run_fn.call() })); + } + Err(msg) => { + if !msg.is_empty() { + ui.colored_label(egui::Color32::from_rgb(255, 0, 0), msg); + } + } + }; + }); + } + } +} + +fn main() -> eframe::Result { + inkwell::targets::Target::initialize_all(&inkwell::targets::InitializationConfig::default()); + + let options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default().with_inner_size([1024.0, 768.0]), + ..Default::default() + }; + + let mut cells = Cells::new(); + + eframe::run_simple_native("Cells", options, move |ctx, _frame| { + let submit_key = egui::KeyboardShortcut::new(egui::Modifiers::CTRL, egui::Key::Enter); + if ctx.input_mut(|input| input.consume_shortcut(&submit_key)) { + cells.update(); + cells.ensure_last(); + } + + egui::CentralPanel::default().show(ctx, |ui| { + cells.ui(ui); }); }) }