From 4d50c8c1be0b3c05da1b8275ebf11fdef07abc4d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 14 Jun 2026 03:22:41 +0200 Subject: [PATCH 01/11] Map generation is separated --- crates/codegen/src/lib.rs | 39 +++++++++++++++++++-------- crates/codegen/src/top_level.rs | 8 ++++-- crates/parser/src/rev_mapper/mod.rs | 41 +++++------------------------ 3 files changed, 41 insertions(+), 47 deletions(-) diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 03ac6b5..e3f1af9 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -3,7 +3,12 @@ pub mod expr; pub mod statement; pub mod top_level; -use mist_parser::ast::*; +use std::collections::HashSet; + +use mist_parser::{ + ast::*, + rev_mapper::{MistMap, RustMap}, +}; pub struct Context { pub expr_ensure_semicolon: bool, @@ -26,6 +31,8 @@ pub trait GetRust { pub struct RustCodegen { output: String, indent: usize, + mapping: HashSet<(RustMap, MistMap)>, + position: RustMap, } impl RustCodegen { @@ -33,6 +40,8 @@ impl RustCodegen { Self { output: String::new(), indent: 0, + mapping: HashSet::new(), + position: RustMap(0, 0), } } @@ -41,6 +50,18 @@ impl RustCodegen { } fn add(&mut self, s: &str) { + for c in s.chars() { + match c { + '\n' => { + self.position.0 += 1; + self.position.1 = 0; + } + _ => { + self.position.1 += 1; + } + } + } + self.output.push_str(s); } @@ -123,21 +144,17 @@ impl GenRust for Attribute { } } -impl GetRust for Spanned { - fn get_rust(&self) -> String { - format!( - "/* {}:{} */ {}", - self.line, - self.column, - self.item.get_rust() - ) +impl GenRust for T { + fn gen_rust(&self, _: &mut Context, cg: &mut RustCodegen) { + cg.add(&self.get_rust()); } } impl GenRust for Spanned { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column)); - cg.add_indented(""); + cg.mapping + .insert((cg.position, MistMap(self.line, self.column))); + self.item.gen_rust(ctx, cg); } } diff --git a/crates/codegen/src/top_level.rs b/crates/codegen/src/top_level.rs index 1af2afa..39bfbb8 100644 --- a/crates/codegen/src/top_level.rs +++ b/crates/codegen/src/top_level.rs @@ -195,7 +195,9 @@ impl GenRust for TopLevelKind { cg.indent += 1; for field in fields { - cg.add_indentedln(&field.get_rust()); + cg.add_indented(""); + field.gen_rust(ctx, cg); + cg.addln(""); } cg.indent -= 1; @@ -216,7 +218,9 @@ impl GenRust for TopLevelKind { cg.indent += 1; for field in fields { - cg.add_indentedln(&(field.get_rust() + ",")); + cg.add_indented(""); + field.gen_rust(ctx, cg); + cg.addln(","); } cg.indent -= 1; diff --git a/crates/parser/src/rev_mapper/mod.rs b/crates/parser/src/rev_mapper/mod.rs index 3e7a4d0..a251f5a 100644 --- a/crates/parser/src/rev_mapper/mod.rs +++ b/crates/parser/src/rev_mapper/mod.rs @@ -1,44 +1,17 @@ use std::collections::HashSet; -use pest::Parser; -use pest_derive::Parser; +use serde::{Deserialize, Serialize}; -#[derive(Parser)] -#[grammar = "./src/rev_mapper/grammar.pest"] -pub struct MistMapperParser; - -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive( + Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, +)] pub struct MistMap(pub usize, pub usize); -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive( + Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, +)] pub struct RustMap(pub usize, pub usize); -pub fn get_mapping(input: &str) -> HashSet<(RustMap, MistMap)> { - let mut mapping = HashSet::new(); - - let pairs = MistMapperParser::parse(Rule::mapping, input) - .unwrap() - .next() - .unwrap() - .into_inner(); - - for pair in pairs { - if pair.as_rule() == Rule::map { - let rs = pair.as_span().start_pos().line_col(); - let mut inner = pair.into_inner(); - - let (line, col) = ( - inner.next().unwrap().as_str().parse().unwrap(), - inner.next().unwrap().as_str().parse().unwrap(), - ); - - mapping.insert((RustMap(rs.0, rs.1), MistMap(line, col))); - } - } - - mapping -} - pub fn find_mapping( mapping: &HashSet<(RustMap, MistMap)>, target: &RustMap, From db3ae3f37ec693a2566a37b9dab21c172259da33 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 14 Jun 2026 03:57:48 +0200 Subject: [PATCH 02/11] Temp disable old err mapping --- crates/analyzer/src/builder.rs | 70 ++++++++++++++++---------------- crates/analyzer/src/lib.rs | 24 +++++------ crates/mist-api/src/builder.mist | 70 ++++++++++++++++---------------- 3 files changed, 82 insertions(+), 82 deletions(-) diff --git a/crates/analyzer/src/builder.rs b/crates/analyzer/src/builder.rs index 2522602..20b24c9 100644 --- a/crates/analyzer/src/builder.rs +++ b/crates/analyzer/src/builder.rs @@ -6,7 +6,7 @@ use std::{ }; use cargo_metadata::{CompilerMessage, Message}; -use mist_parser::rev_mapper::{RustMap, find_mapping, get_mapping}; +use mist_parser::rev_mapper::{self, RustMap, find_mapping}; #[derive(Debug, Clone)] pub struct MistDiagnosticMessage { @@ -39,7 +39,7 @@ pub fn build(mut args: Vec, root: PathBuf) -> Vec { let mut diagnostics = Vec::new(); - let mut mapping = HashMap::new(); + let mut mapping: HashMap = HashMap::new(); let mist_src = format!(".mist{MAIN_SEPARATOR}lsp"); @@ -64,44 +64,44 @@ pub fn build(mut args: Vec, root: PathBuf) -> Vec { break; } - let map = mapping.entry(rust_path.clone()).or_insert_with(|| { - get_mapping( - &fs::read_to_string(rust_path) - .expect("Failed to read file for mapping"), - ) - }); + // let map = mapping.entry(rust_path.clone()).or_insert_with(|| { + // get_mapping( + // &fs::read_to_string(rust_path) + // .expect("Failed to read file for mapping"), + // ) + // }); - let mist_span = - find_mapping(&map, &RustMap(span.line_end, span.column_start)) - .expect("Unable to find mapping"); + // let mist_span = + // find_mapping(&map, &RustMap(span.line_end, span.column_start)) + // .expect("Unable to find mapping"); - let mist_msg = MistDiagnosticMessage { - message: format!( - "{}: {}", - msg.message.message, - span.label.clone().unwrap_or_default() - ), - file_name: if is_root { - mist_file - } else { - mist_path.to_string_lossy().to_string() - }, - file_path: mist_path, - line: mist_span.1.0, - column: mist_span.1.1, - }; + // let mist_msg = MistDiagnosticMessage { + // message: format!( + // "{}: {}", + // msg.message.message, + // span.label.clone().unwrap_or_default() + // ), + // file_name: if is_root { + // mist_file + // } else { + // mist_path.to_string_lossy().to_string() + // }, + // file_path: mist_path, + // line: mist_span.1.0, + // column: mist_span.1.1, + // }; - match msg.message.level { - cargo_metadata::diagnostic::DiagnosticLevel::Error => { - diagnostics.push(MistDiagnostic::Error(mist_msg)) - } + // match msg.message.level { + // cargo_metadata::diagnostic::DiagnosticLevel::Error => { + // diagnostics.push(MistDiagnostic::Error(mist_msg)) + // } - cargo_metadata::diagnostic::DiagnosticLevel::Warning => { - diagnostics.push(MistDiagnostic::Warning(mist_msg)) - } + // cargo_metadata::diagnostic::DiagnosticLevel::Warning => { + // diagnostics.push(MistDiagnostic::Warning(mist_msg)) + // } - _ => {} - } + // _ => {} + // } } } } diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index 366eb5d..d22c66f 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -167,10 +167,10 @@ impl LanguageServer for Backend { .insert(file.clone(), Rope::from_str(&text)); // store mapping - mapping - .lock() - .await - .insert(rust_path, rev_mapper::get_mapping(&transpiled)); + // mapping + // .lock() + // .await + // .insert(rust_path, rev_mapper::get_mapping(&transpiled)); } } } @@ -311,10 +311,10 @@ impl LanguageServer for Backend { params.text_document.uri = Url::from_file_path(&rust_path).unwrap(); - self.mapping.lock().await.insert( - rust_path, - rev_mapper::get_mapping(¶ms.text_document.text), - ); + // self.mapping.lock().await.insert( + // rust_path, + // rev_mapper::get_mapping(¶ms.text_document.text), + // ); } Err(e) => { self.client @@ -353,10 +353,10 @@ impl LanguageServer for Backend { Ok(transpiled_text) => { change.text = transpiled_text; - self.mapping - .lock() - .await - .insert(rust_path, rev_mapper::get_mapping(&change.text)); + // self.mapping + // .lock() + // .await + // .insert(rust_path, rev_mapper::get_mapping(&change.text)); } Err(e) => { self.client diff --git a/crates/mist-api/src/builder.mist b/crates/mist-api/src/builder.mist index dd94ee7..fc7bf76 100644 --- a/crates/mist-api/src/builder.mist +++ b/crates/mist-api/src/builder.mist @@ -45,7 +45,7 @@ pub fn build(mut args Vec, root PathBuf) bool { let mut diagnostics = Vec::new(); - let mut mapping = HashMap::new(); + let mut mapping HashMap = HashMap::new(); let mist_src = format!(".mist{MAIN_SEPARATOR}src"); @@ -70,45 +70,45 @@ pub fn build(mut args Vec, root PathBuf) bool { break; } - let map = mapping.entry(rust_path.clone()).or_insert_with(fn() { - rev_mapper::get_mapping( - &fs::read_to_string(rust_path) - .expect("Failed to read file for mapping") - ) - }); + // let map = mapping.entry(rust_path.clone()).or_insert_with(fn() { + // rev_mapper::get_mapping( + // &fs::read_to_string(rust_path) + // .expect("Failed to read file for mapping") + // ) + // }); - let [_, rev_mapper::MistMap[line, column]] = - rev_mapper::find_mapping(&map, &rev_mapper::RustMap(span.line_end, span.column_start)) - .expect("Unable to find mapping"); + // let [_, rev_mapper::MistMap[line, column]] = + // rev_mapper::find_mapping(&map, &rev_mapper::RustMap(span.line_end, span.column_start)) + // .expect("Unable to find mapping"); - let mist_msg = MistDiagnosticMessage { - message: format!( - "{}: {}", - msg.message.message, - span.label.clone().unwrap_or_default() - ), - file_name: if is_root { - (); // TODO: fix this - mist_file - } else { - mist_path.to_string_lossy().to_string() - }, - file_path: mist_path, - line: line, - column: column - }; + // let mist_msg = MistDiagnosticMessage { + // message: format!( + // "{}: {}", + // msg.message.message, + // span.label.clone().unwrap_or_default() + // ), + // file_name: if is_root { + // (); // TODO: fix this + // mist_file + // } else { + // mist_path.to_string_lossy().to_string() + // }, + // file_path: mist_path, + // line: line, + // column: column + // }; - match msg.message.level { - cargo_metadata::diagnostic::DiagnosticLevel::Error => { - diagnostics.push(MistDiagnostic::Error(mist_msg)) - } + // match msg.message.level { + // cargo_metadata::diagnostic::DiagnosticLevel::Error => { + // diagnostics.push(MistDiagnostic::Error(mist_msg)) + // } - cargo_metadata::diagnostic::DiagnosticLevel::Warning => { - diagnostics.push(MistDiagnostic::Warning(mist_msg)) - } + // cargo_metadata::diagnostic::DiagnosticLevel::Warning => { + // diagnostics.push(MistDiagnostic::Warning(mist_msg)) + // } - _ => {} - } + // _ => {} + // } } } } From 33d6c931f503fc3e3c1ca5f45e2a4823a13e084c Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 14 Jun 2026 04:06:39 +0200 Subject: [PATCH 03/11] Working map gen --- crates/codegen/src/lib.rs | 2 +- crates/mist-api/src/transpiler.mist | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index e3f1af9..0abb496 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -31,7 +31,7 @@ pub trait GetRust { pub struct RustCodegen { output: String, indent: usize, - mapping: HashSet<(RustMap, MistMap)>, + pub mapping: HashSet<(RustMap, MistMap)>, position: RustMap, } diff --git a/crates/mist-api/src/transpiler.mist b/crates/mist-api/src/transpiler.mist index ba66a5f..d25f276 100644 --- a/crates/mist-api/src/transpiler.mist +++ b/crates/mist-api/src/transpiler.mist @@ -238,13 +238,27 @@ fn transpile_file(path *PathBuf, source *str, mut output_file PathBuf, mod_decl let res = fs::write(&output_file, format!("{mod_decl}{output}")); + let output_file_map = output_file.with_extension("map.json"); + + let res_map = fs::write(&output_file_map, serde_json::to_string(&gc.mapping).unwrap()); + + if res_map.is_err() { + eprintln!( + "error: failed to write mapping output {}\n {}", + output_file_map.display(), + res.as_ref().unwrap_err(), + ); + } + if res.is_err() { eprintln!( "error: failed to write output {}\n {}", output_file.display(), - res.unwrap_err(), + res.as_ref().unwrap_err(), ); + } + if res_map.is_err() || res.is_err() { process::exit(1); } } From 37e0a574d57708932f3b76347b8fbfc2feafb641 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 14 Jun 2026 04:18:57 +0200 Subject: [PATCH 04/11] Working map shift gen --- crates/mist-api/src/transpiler.mist | 3 +++ crates/parser/src/rev_mapper/mod.rs | 32 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/crates/mist-api/src/transpiler.mist b/crates/mist-api/src/transpiler.mist index d25f276..2c32c94 100644 --- a/crates/mist-api/src/transpiler.mist +++ b/crates/mist-api/src/transpiler.mist @@ -8,6 +8,7 @@ use std::time; use std::env; use mist_parser::error; +use mist_parser::rev_mapper; use crate::modules; use mist_codegen::GetRust; @@ -238,6 +239,8 @@ fn transpile_file(path *PathBuf, source *str, mut output_file PathBuf, mod_decl let res = fs::write(&output_file, format!("{mod_decl}{output}")); + rev_mapper::shift_rust_mappings(&mut gc.mapping, mod_decl.lines().count() as isize, 0); + let output_file_map = output_file.with_extension("map.json"); let res_map = fs::write(&output_file_map, serde_json::to_string(&gc.mapping).unwrap()); diff --git a/crates/parser/src/rev_mapper/mod.rs b/crates/parser/src/rev_mapper/mod.rs index a251f5a..bb08513 100644 --- a/crates/parser/src/rev_mapper/mod.rs +++ b/crates/parser/src/rev_mapper/mod.rs @@ -22,3 +22,35 @@ pub fn find_mapping( .filter(|(rust, _)| rust <= target) .max_by_key(|(rust, _)| *rust) } + +impl RustMap { + pub fn shifted(self, lines: isize, cols: isize) -> Self { + Self( + self.0.saturating_add_signed(lines), + self.1.saturating_add_signed(cols), + ) + } +} + +impl MistMap { + pub fn shifted(self, lines: isize, cols: isize) -> Self { + Self( + self.0.saturating_add_signed(lines), + self.1.saturating_add_signed(cols), + ) + } +} + +pub fn shift_rust_mappings(mappings: &mut HashSet<(RustMap, MistMap)>, lines: isize, cols: isize) { + *mappings = mappings + .iter() + .map(|(rust, mist)| (rust.shifted(lines, cols), *mist)) + .collect(); +} + +pub fn shift_mist_mappings(mappings: &mut HashSet<(RustMap, MistMap)>, lines: isize, cols: isize) { + *mappings = mappings + .iter() + .map(|(rust, mist)| (*rust, mist.shifted(lines, cols))) + .collect(); +} From 5f0b1fa67ad9e106d00ab1c0f35e3c69820f67c3 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 15 Jun 2026 14:12:33 +0200 Subject: [PATCH 05/11] Working mapgen and fixed indentation --- crates/codegen/src/lib.rs | 17 +++++++---------- crates/codegen/src/statement.rs | 2 ++ crates/codegen/src/top_level.rs | 5 +++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 0abb496..0c8929e 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -41,7 +41,7 @@ impl RustCodegen { output: String::new(), indent: 0, mapping: HashSet::new(), - position: RustMap(0, 0), + position: RustMap(1, 0), } } @@ -50,15 +50,12 @@ impl RustCodegen { } fn add(&mut self, s: &str) { - for c in s.chars() { - match c { - '\n' => { - self.position.0 += 1; - self.position.1 = 0; - } - _ => { - self.position.1 += 1; - } + for b in s.bytes() { + if b == b'\n' { + self.position.0 += 1; + self.position.1 = 0; + } else { + self.position.1 += 1; } } diff --git a/crates/codegen/src/statement.rs b/crates/codegen/src/statement.rs index 4d0229f..f1596ee 100644 --- a/crates/codegen/src/statement.rs +++ b/crates/codegen/src/statement.rs @@ -11,12 +11,14 @@ impl GenRust for Block { for stmt in &self.statements { ctx.expr_ensure_semicolon = true; + cg.add_indented(""); stmt.gen_rust(ctx, cg); cg.addln(""); } if let Some(soft_return) = &self.soft_return { ctx.expr_ensure_semicolon = false; + cg.add_indented(""); soft_return.gen_rust(ctx, cg); cg.addln(""); } diff --git a/crates/codegen/src/top_level.rs b/crates/codegen/src/top_level.rs index 39bfbb8..5bda42f 100644 --- a/crates/codegen/src/top_level.rs +++ b/crates/codegen/src/top_level.rs @@ -73,7 +73,7 @@ impl GenRust for ImplDecl { impl GenRust for FunctionDecl { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add(&format!( + cg.add_indented(&format!( "{}fn {}{}(", self.visibility.get_rust(), self.name.get_rust(), @@ -97,8 +97,9 @@ impl GenRust for FunctionDecl { if let Some(body) = &self.body { cg.add(" "); body.gen_rust(ctx, cg); + cg.addln(""); } else { - cg.add(";"); + cg.addln(";"); } } } From bed7b17134e0dd1d55b0414e9bc9329d807d56c7 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 15 Jun 2026 14:21:53 +0200 Subject: [PATCH 06/11] Made add in codegen faster --- Cargo.lock | 7 +++++++ crates/codegen/Cargo.toml | 1 + crates/codegen/src/lib.rs | 18 ++++++++++-------- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86252ec..d67b7cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bytecount" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" + [[package]] name = "bytes" version = "1.11.1" @@ -493,6 +499,7 @@ dependencies = [ name = "mist-codegen" version = "0.3.3-alpha.0" dependencies = [ + "bytecount", "mist-parser", ] diff --git a/crates/codegen/Cargo.toml b/crates/codegen/Cargo.toml index f4a00bc..2f946b0 100644 --- a/crates/codegen/Cargo.toml +++ b/crates/codegen/Cargo.toml @@ -9,4 +9,5 @@ keywords = ["compiler", "language", "mist"] categories = ["compilers"] [dependencies] +bytecount = "0.6.9" mist-parser = { workspace = true } diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 0c8929e..d900a5b 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -50,15 +50,17 @@ impl RustCodegen { } fn add(&mut self, s: &str) { - for b in s.bytes() { - if b == b'\n' { - self.position.0 += 1; - self.position.1 = 0; - } else { - self.position.1 += 1; - } + let newline_count = bytecount::count(s.as_bytes(), b'\n'); + + if newline_count == 0 { + self.position.1 += s.len(); + } else { + self.position.0 += newline_count; + + let last_newline = s.rfind('\n').unwrap(); + self.position.1 = s.len() - last_newline - 1; } - + self.output.push_str(s); } From 44f10d3fb7bc16d4aa98c6a8da4870be9dd0f7a4 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 15 Jun 2026 14:32:51 +0200 Subject: [PATCH 07/11] Updated builder with new mapping --- crates/mist-api/src/builder.mist | 73 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/crates/mist-api/src/builder.mist b/crates/mist-api/src/builder.mist index fc7bf76..3f3295a 100644 --- a/crates/mist-api/src/builder.mist +++ b/crates/mist-api/src/builder.mist @@ -45,7 +45,7 @@ pub fn build(mut args Vec, root PathBuf) bool { let mut diagnostics = Vec::new(); - let mut mapping HashMap = HashMap::new(); + let mut mapping = HashMap::new(); let mist_src = format!(".mist{MAIN_SEPARATOR}src"); @@ -65,50 +65,51 @@ pub fn build(mut args Vec, root PathBuf) bool { let mist_path = root.join(&mist_file); - if !fs::exists(&mist_path).expect("Unable to check if mist file exists") { + let mapping_path = rust_path.with_extension("map.json"); + + if !fs::exists(&mapping_path).expect("Unable to check if map file exists") { diagnostics.push(MistDiagnostic::Rust(msg)); break; } - // let map = mapping.entry(rust_path.clone()).or_insert_with(fn() { - // rev_mapper::get_mapping( - // &fs::read_to_string(rust_path) - // .expect("Failed to read file for mapping") - // ) - // }); + let map = mapping.entry(mapping_path.clone()).or_insert_with(fn() { + let map_str = fs::read_to_string(mapping_path).expect("Failed to read map file"); - // let [_, rev_mapper::MistMap[line, column]] = - // rev_mapper::find_mapping(&map, &rev_mapper::RustMap(span.line_end, span.column_start)) - // .expect("Unable to find mapping"); + serde_json::from_str(&map_str).expect("Failed to parse map file") + }); - // let mist_msg = MistDiagnosticMessage { - // message: format!( - // "{}: {}", - // msg.message.message, - // span.label.clone().unwrap_or_default() - // ), - // file_name: if is_root { - // (); // TODO: fix this - // mist_file - // } else { - // mist_path.to_string_lossy().to_string() - // }, - // file_path: mist_path, - // line: line, - // column: column - // }; + let [_, rev_mapper::MistMap[line, column]] = + rev_mapper::find_mapping(&map, &rev_mapper::RustMap(span.line_end, span.column_start)) + .expect("Unable to find mapping"); - // match msg.message.level { - // cargo_metadata::diagnostic::DiagnosticLevel::Error => { - // diagnostics.push(MistDiagnostic::Error(mist_msg)) - // } + let mist_msg = MistDiagnosticMessage { + message: format!( + "{}: {}", + msg.message.message, + span.label.clone().unwrap_or_default() + ), + file_name: if is_root { + (); // TODO: fix this + mist_file + } else { + mist_path.to_string_lossy().to_string() + }, + file_path: mist_path, + line: line, + column: column + }; - // cargo_metadata::diagnostic::DiagnosticLevel::Warning => { - // diagnostics.push(MistDiagnostic::Warning(mist_msg)) - // } + match msg.message.level { + cargo_metadata::diagnostic::DiagnosticLevel::Error => { + diagnostics.push(MistDiagnostic::Error(mist_msg)) + } - // _ => {} - // } + cargo_metadata::diagnostic::DiagnosticLevel::Warning => { + diagnostics.push(MistDiagnostic::Warning(mist_msg)) + } + + _ => {} + } } } } From 663dab52ecde019da73fdc6721808b974b83cdb8 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 15 Jun 2026 14:49:44 +0200 Subject: [PATCH 08/11] Updated mapping data structure --- crates/analyzer/src/builder.rs | 2 +- crates/analyzer/src/lib.rs | 45 +++++++++++---------- crates/analyzer/src/transpiler.rs | 17 ++++---- crates/codegen/src/lib.rs | 18 ++++----- crates/parser/src/rev_mapper/mod.rs | 62 ++++++++++++++++++----------- 5 files changed, 81 insertions(+), 63 deletions(-) diff --git a/crates/analyzer/src/builder.rs b/crates/analyzer/src/builder.rs index 20b24c9..7f8ecfc 100644 --- a/crates/analyzer/src/builder.rs +++ b/crates/analyzer/src/builder.rs @@ -6,7 +6,7 @@ use std::{ }; use cargo_metadata::{CompilerMessage, Message}; -use mist_parser::rev_mapper::{self, RustMap, find_mapping}; +use mist_parser::rev_mapper; #[derive(Debug, Clone)] pub struct MistDiagnosticMessage { diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index d22c66f..5569ad2 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -57,29 +57,30 @@ impl Backend { match self.mapping.lock().await.get(&rs_path) { Some(mapping) => { + rs_loc // FIX: Match the find_mapping operation instead of calling .expect("Failed to map") - match rev_mapper::find_mapping( - mapping, - &rev_mapper::RustMap( - rs_loc.range.start.line as usize, - rs_loc.range.start.character as usize, - ), - ) { - Some((_, rev_mapper::MistMap(line, character))) => Location { - uri: Url::from_file_path(from_rust_to_mist(rs_path)).unwrap(), - range: Range { - start: Position { - line: line as u32 - 1, - character: character as u32, - }, - end: Position { - line: line as u32 - 1, - character: character as u32 + 1, - }, - }, - }, - None => rs_loc, - } + // match rev_mapper::find_mapping( + // mapping, + // &rev_mapper::RustMap( + // rs_loc.range.start.line as usize, + // rs_loc.range.start.character as usize, + // ), + // ) { + // Some((_, rev_mapper::MistMap(line, character))) => Location { + // uri: Url::from_file_path(from_rust_to_mist(rs_path)).unwrap(), + // range: Range { + // start: Position { + // line: line as u32 - 1, + // character: character as u32, + // }, + // end: Position { + // line: line as u32 - 1, + // character: character as u32 + 1, + // }, + // }, + // }, + // None => rs_loc, + // } } None => rs_loc, } diff --git a/crates/analyzer/src/transpiler.rs b/crates/analyzer/src/transpiler.rs index 66a316c..e3baed3 100644 --- a/crates/analyzer/src/transpiler.rs +++ b/crates/analyzer/src/transpiler.rs @@ -135,19 +135,22 @@ pub fn transpile_file(path: &Path, output_path: &Path) -> Result<(), String> { // If parsing fails, return the error string back gracefully so the LSP can show it let ast = parser_result.map_err(|e| format!("parse failed in {}:\n{}", path.display(), e))?; - let mut gc = mist_codegen::RustCodegen::new(); - let output = gc.generate(ast); + panic!(); - fs::write(output_path, output) - .map_err(|e| format!("failed to write output {}: {}", output_path.display(), e))?; + // let mut gc = mist_codegen::RustCodegen::new(); + // let output = gc.generate(ast); - Ok(()) + // fs::write(output_path, output) + // .map_err(|e| format!("failed to write output {}: {}", output_path.display(), e))?; + + // Ok(()) } pub fn transpile_text<'a>(source: &'a str) -> Result>> { - let mut gc = mist_codegen::RustCodegen::new(); + panic!(); + // let mut gc = mist_codegen::RustCodegen::new(); - Ok(gc.generate(mist_parser::parse(&source)?)) + // Ok(gc.generate(mist_parser::parse(&source)?)) } fn should_skip(source: &Path, output: &Path) -> bool { diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index d900a5b..6b17a85 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -3,11 +3,11 @@ pub mod expr; pub mod statement; pub mod top_level; -use std::collections::HashSet; +use std::path::PathBuf; use mist_parser::{ ast::*, - rev_mapper::{MistMap, RustMap}, + rev_mapper::{Mapping, MistMap, RustMap}, }; pub struct Context { @@ -27,20 +27,19 @@ pub trait GetRust { } } -#[derive(Default)] pub struct RustCodegen { output: String, indent: usize, - pub mapping: HashSet<(RustMap, MistMap)>, + pub mapping: Mapping, position: RustMap, } impl RustCodegen { - pub fn new() -> Self { + pub fn new(mist_path: PathBuf) -> Self { Self { output: String::new(), indent: 0, - mapping: HashSet::new(), + mapping: Mapping::new(mist_path), position: RustMap(1, 0), } } @@ -51,16 +50,16 @@ impl RustCodegen { fn add(&mut self, s: &str) { let newline_count = bytecount::count(s.as_bytes(), b'\n'); - + if newline_count == 0 { self.position.1 += s.len(); } else { self.position.0 += newline_count; - + let last_newline = s.rfind('\n').unwrap(); self.position.1 = s.len() - last_newline - 1; } - + self.output.push_str(s); } @@ -152,6 +151,7 @@ impl GenRust for T { impl GenRust for Spanned { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { cg.mapping + .map .insert((cg.position, MistMap(self.line, self.column))); self.item.gen_rust(ctx, cg); diff --git a/crates/parser/src/rev_mapper/mod.rs b/crates/parser/src/rev_mapper/mod.rs index bb08513..e943792 100644 --- a/crates/parser/src/rev_mapper/mod.rs +++ b/crates/parser/src/rev_mapper/mod.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::{collections::HashSet, path::PathBuf}; use serde::{Deserialize, Serialize}; @@ -12,15 +12,43 @@ pub struct MistMap(pub usize, pub usize); )] pub struct RustMap(pub usize, pub usize); -pub fn find_mapping( - mapping: &HashSet<(RustMap, MistMap)>, - target: &RustMap, -) -> Option<(RustMap, MistMap)> { - mapping - .iter() - .copied() - .filter(|(rust, _)| rust <= target) - .max_by_key(|(rust, _)| *rust) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Mapping { + pub mist_path: PathBuf, + pub map: HashSet<(RustMap, MistMap)>, +} + +impl Mapping { + pub fn new(mist_path: PathBuf) -> Self { + Self { + mist_path, + map: HashSet::new(), + } + } + + pub fn find(&self, target: &RustMap) -> Option<(RustMap, MistMap)> { + self.map + .iter() + .copied() + .filter(|(rust, _)| rust <= target) + .max_by_key(|(rust, _)| *rust) + } + + pub fn shift_rust(&mut self, lines: isize, cols: isize) { + self.map = self + .map + .iter() + .map(|(rust, mist)| (rust.shifted(lines, cols), *mist)) + .collect(); + } + + pub fn shift_mist(&mut self, lines: isize, cols: isize) { + self.map = self + .map + .iter() + .map(|(rust, mist)| (*rust, mist.shifted(lines, cols))) + .collect(); + } } impl RustMap { @@ -40,17 +68,3 @@ impl MistMap { ) } } - -pub fn shift_rust_mappings(mappings: &mut HashSet<(RustMap, MistMap)>, lines: isize, cols: isize) { - *mappings = mappings - .iter() - .map(|(rust, mist)| (rust.shifted(lines, cols), *mist)) - .collect(); -} - -pub fn shift_mist_mappings(mappings: &mut HashSet<(RustMap, MistMap)>, lines: isize, cols: isize) { - *mappings = mappings - .iter() - .map(|(rust, mist)| (*rust, mist.shifted(lines, cols))) - .collect(); -} From 12cf4e94d8b17ca0c189d68d4701dc2b0ae12836 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 15 Jun 2026 15:04:10 +0200 Subject: [PATCH 09/11] Implemented updated mapping data structure --- crates/mist-api/src/builder.mist | 26 ++++++++------------------ crates/mist-api/src/transpiler.mist | 5 ++--- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/crates/mist-api/src/builder.mist b/crates/mist-api/src/builder.mist index 3f3295a..1feb6df 100644 --- a/crates/mist-api/src/builder.mist +++ b/crates/mist-api/src/builder.mist @@ -31,8 +31,6 @@ pub fn build(mut args Vec, root PathBuf) bool { args.remove(0); args.insert(1, "--message-format=json".to_string()); - let is_root = root == env::current_dir().expect("Failed getting env"); - let mut command = Command::new("cargo") .args(args) .stdout(Stdio::piped()) @@ -56,15 +54,6 @@ pub fn build(mut args Vec, root PathBuf) bool { if span.is_primary { let rust_path = root.join(&span.file_name); - let mist_file = span - .file_name - .replacen(&mist_src, "src", 1) - .trim_end_matches(".rs") - .to_string() - + ".mist"; - - let mist_path = root.join(&mist_file); - let mapping_path = rust_path.with_extension("map.json"); if !fs::exists(&mapping_path).expect("Unable to check if map file exists") { @@ -75,11 +64,13 @@ pub fn build(mut args Vec, root PathBuf) bool { let map = mapping.entry(mapping_path.clone()).or_insert_with(fn() { let map_str = fs::read_to_string(mapping_path).expect("Failed to read map file"); - serde_json::from_str(&map_str).expect("Failed to parse map file") + serde_json::from_str(&map_str).expect("Failed to parse map file") }); + let mist_file = map.mist_path.strip_prefix(&root); + let [_, rev_mapper::MistMap[line, column]] = - rev_mapper::find_mapping(&map, &rev_mapper::RustMap(span.line_end, span.column_start)) + map.find(&rev_mapper::RustMap(span.line_end, span.column_start)) .expect("Unable to find mapping"); let mist_msg = MistDiagnosticMessage { @@ -88,13 +79,12 @@ pub fn build(mut args Vec, root PathBuf) bool { msg.message.message, span.label.clone().unwrap_or_default() ), - file_name: if is_root { - (); // TODO: fix this - mist_file + file_name: if let Ok(mist_file) = mist_file { + mist_file.to_string_lossy().to_string() } else { - mist_path.to_string_lossy().to_string() + map.mist_path.to_string_lossy().to_string() }, - file_path: mist_path, + file_path: map.mist_path.clone(), line: line, column: column }; diff --git a/crates/mist-api/src/transpiler.mist b/crates/mist-api/src/transpiler.mist index 2c32c94..42a8302 100644 --- a/crates/mist-api/src/transpiler.mist +++ b/crates/mist-api/src/transpiler.mist @@ -8,7 +8,6 @@ use std::time; use std::env; use mist_parser::error; -use mist_parser::rev_mapper; use crate::modules; use mist_codegen::GetRust; @@ -201,7 +200,7 @@ fn transpile_file(path *PathBuf, source *str, mut output_file PathBuf, mod_decl } } - let mut gc = mist_codegen::RustCodegen::new(); + let mut gc = mist_codegen::RustCodegen::new(path.clone()); let parsed = match mist_parser::parse(source) { Ok[ast] => ast; @@ -239,7 +238,7 @@ fn transpile_file(path *PathBuf, source *str, mut output_file PathBuf, mod_decl let res = fs::write(&output_file, format!("{mod_decl}{output}")); - rev_mapper::shift_rust_mappings(&mut gc.mapping, mod_decl.lines().count() as isize, 0); + gc.mapping.shift_rust(mod_decl.lines().count() as isize, 0); let output_file_map = output_file.with_extension("map.json"); From 116384903963c379eee8060404161a07e113c2aa Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 15 Jun 2026 15:08:48 +0200 Subject: [PATCH 10/11] Fixed class method indentation --- crates/codegen/src/class_decl.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 4e9ae0a..584d5e4 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -522,7 +522,7 @@ fn construct_pattern(pat: &Pattern, idx: usize) -> Pattern { } pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add(&format!( + cg.add_indented(&format!( "{}fn {}{}(", method.visibility.get_rust(), method.name.get_rust(), From 6b618f3eb3cd5ab84b431c6a220fe3ff71e0b254 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Mon, 15 Jun 2026 15:21:49 +0200 Subject: [PATCH 11/11] Removed warnings from api --- crates/mist-api/src/builder.mist | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/mist-api/src/builder.mist b/crates/mist-api/src/builder.mist index 1feb6df..990ccd1 100644 --- a/crates/mist-api/src/builder.mist +++ b/crates/mist-api/src/builder.mist @@ -1,9 +1,7 @@ pub module builder; use std::collections::HashMap; -use std::env; use std::fs; -use std::path::MAIN_SEPARATOR; use std::path::PathBuf; use std::process::Command; use std::process::Stdio; @@ -45,8 +43,6 @@ pub fn build(mut args Vec, root PathBuf) bool { let mut mapping = HashMap::new(); - let mist_src = format!(".mist{MAIN_SEPARATOR}src"); - for message in cargo_metadata::Message::parse_stream(&mut reader) { match message { Ok[Message::CompilerMessage[msg]] => {