create cells

This commit is contained in:
Sebastien Bourdeauducq 2024-09-07 10:06:51 +08:00
parent 4ac0bf317b
commit f0a492fc20
1 changed files with 104 additions and 40 deletions

View File

@ -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<inkwell::execution_engine::JitFunction<'a, RunFn>, 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<Run> =
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<inkwell::execution_engine::JitFunction<'a, RunFn>, 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<Cell<'a>>,
}
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);
});
})
}