Merge pull request #78 from mist-go/rewrite-map-system

Rewrite map system
This commit is contained in:
2026-06-15 15:34:59 +02:00
committed by GitHub
12 changed files with 217 additions and 160 deletions
Generated
+7
View File
@@ -45,6 +45,12 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bytecount"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.11.1" version = "1.11.1"
@@ -493,6 +499,7 @@ dependencies = [
name = "mist-codegen" name = "mist-codegen"
version = "0.3.3-alpha.0" version = "0.3.3-alpha.0"
dependencies = [ dependencies = [
"bytecount",
"mist-parser", "mist-parser",
] ]
+35 -35
View File
@@ -6,7 +6,7 @@ use std::{
}; };
use cargo_metadata::{CompilerMessage, Message}; use cargo_metadata::{CompilerMessage, Message};
use mist_parser::rev_mapper::{RustMap, find_mapping, get_mapping}; use mist_parser::rev_mapper;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MistDiagnosticMessage { pub struct MistDiagnosticMessage {
@@ -39,7 +39,7 @@ pub fn build(mut args: Vec<String>, root: PathBuf) -> Vec<MistDiagnostic> {
let mut diagnostics = Vec::new(); let mut diagnostics = Vec::new();
let mut mapping = HashMap::new(); let mut mapping: HashMap<rev_mapper::RustMap, rev_mapper::MistMap> = HashMap::new();
let mist_src = format!(".mist{MAIN_SEPARATOR}lsp"); let mist_src = format!(".mist{MAIN_SEPARATOR}lsp");
@@ -64,44 +64,44 @@ pub fn build(mut args: Vec<String>, root: PathBuf) -> Vec<MistDiagnostic> {
break; break;
} }
let map = mapping.entry(rust_path.clone()).or_insert_with(|| { // let map = mapping.entry(rust_path.clone()).or_insert_with(|| {
get_mapping( // get_mapping(
&fs::read_to_string(rust_path) // &fs::read_to_string(rust_path)
.expect("Failed to read file for mapping"), // .expect("Failed to read file for mapping"),
) // )
}); // });
let mist_span = // let mist_span =
find_mapping(&map, &RustMap(span.line_end, span.column_start)) // find_mapping(&map, &RustMap(span.line_end, span.column_start))
.expect("Unable to find mapping"); // .expect("Unable to find mapping");
let mist_msg = MistDiagnosticMessage { // let mist_msg = MistDiagnosticMessage {
message: format!( // message: format!(
"{}: {}", // "{}: {}",
msg.message.message, // msg.message.message,
span.label.clone().unwrap_or_default() // span.label.clone().unwrap_or_default()
), // ),
file_name: if is_root { // file_name: if is_root {
mist_file // mist_file
} else { // } else {
mist_path.to_string_lossy().to_string() // mist_path.to_string_lossy().to_string()
}, // },
file_path: mist_path, // file_path: mist_path,
line: mist_span.1.0, // line: mist_span.1.0,
column: mist_span.1.1, // column: mist_span.1.1,
}; // };
match msg.message.level { // match msg.message.level {
cargo_metadata::diagnostic::DiagnosticLevel::Error => { // cargo_metadata::diagnostic::DiagnosticLevel::Error => {
diagnostics.push(MistDiagnostic::Error(mist_msg)) // diagnostics.push(MistDiagnostic::Error(mist_msg))
} // }
cargo_metadata::diagnostic::DiagnosticLevel::Warning => { // cargo_metadata::diagnostic::DiagnosticLevel::Warning => {
diagnostics.push(MistDiagnostic::Warning(mist_msg)) // diagnostics.push(MistDiagnostic::Warning(mist_msg))
} // }
_ => {} // _ => {}
} // }
} }
} }
} }
+35 -34
View File
@@ -57,29 +57,30 @@ impl Backend {
match self.mapping.lock().await.get(&rs_path) { match self.mapping.lock().await.get(&rs_path) {
Some(mapping) => { Some(mapping) => {
rs_loc
// FIX: Match the find_mapping operation instead of calling .expect("Failed to map") // FIX: Match the find_mapping operation instead of calling .expect("Failed to map")
match rev_mapper::find_mapping( // match rev_mapper::find_mapping(
mapping, // mapping,
&rev_mapper::RustMap( // &rev_mapper::RustMap(
rs_loc.range.start.line as usize, // rs_loc.range.start.line as usize,
rs_loc.range.start.character as usize, // rs_loc.range.start.character as usize,
), // ),
) { // ) {
Some((_, rev_mapper::MistMap(line, character))) => Location { // Some((_, rev_mapper::MistMap(line, character))) => Location {
uri: Url::from_file_path(from_rust_to_mist(rs_path)).unwrap(), // uri: Url::from_file_path(from_rust_to_mist(rs_path)).unwrap(),
range: Range { // range: Range {
start: Position { // start: Position {
line: line as u32 - 1, // line: line as u32 - 1,
character: character as u32, // character: character as u32,
}, // },
end: Position { // end: Position {
line: line as u32 - 1, // line: line as u32 - 1,
character: character as u32 + 1, // character: character as u32 + 1,
}, // },
}, // },
}, // },
None => rs_loc, // None => rs_loc,
} // }
} }
None => rs_loc, None => rs_loc,
} }
@@ -167,10 +168,10 @@ impl LanguageServer for Backend {
.insert(file.clone(), Rope::from_str(&text)); .insert(file.clone(), Rope::from_str(&text));
// store mapping // store mapping
mapping // mapping
.lock() // .lock()
.await // .await
.insert(rust_path, rev_mapper::get_mapping(&transpiled)); // .insert(rust_path, rev_mapper::get_mapping(&transpiled));
} }
} }
} }
@@ -311,10 +312,10 @@ impl LanguageServer for Backend {
params.text_document.uri = Url::from_file_path(&rust_path).unwrap(); params.text_document.uri = Url::from_file_path(&rust_path).unwrap();
self.mapping.lock().await.insert( // self.mapping.lock().await.insert(
rust_path, // rust_path,
rev_mapper::get_mapping(&params.text_document.text), // rev_mapper::get_mapping(&params.text_document.text),
); // );
} }
Err(e) => { Err(e) => {
self.client self.client
@@ -353,10 +354,10 @@ impl LanguageServer for Backend {
Ok(transpiled_text) => { Ok(transpiled_text) => {
change.text = transpiled_text; change.text = transpiled_text;
self.mapping // self.mapping
.lock() // .lock()
.await // .await
.insert(rust_path, rev_mapper::get_mapping(&change.text)); // .insert(rust_path, rev_mapper::get_mapping(&change.text));
} }
Err(e) => { Err(e) => {
self.client self.client
+10 -7
View File
@@ -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 // 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 ast = parser_result.map_err(|e| format!("parse failed in {}:\n{}", path.display(), e))?;
let mut gc = mist_codegen::RustCodegen::new(); panic!();
let output = gc.generate(ast);
fs::write(output_path, output) // let mut gc = mist_codegen::RustCodegen::new();
.map_err(|e| format!("failed to write output {}: {}", output_path.display(), e))?; // 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<String, ParseError<'a, Vec<TopLevel>>> { pub fn transpile_text<'a>(source: &'a str) -> Result<String, ParseError<'a, Vec<TopLevel>>> {
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 { fn should_skip(source: &Path, output: &Path) -> bool {
+1
View File
@@ -9,4 +9,5 @@ keywords = ["compiler", "language", "mist"]
categories = ["compilers"] categories = ["compilers"]
[dependencies] [dependencies]
bytecount = "0.6.9"
mist-parser = { workspace = true } mist-parser = { workspace = true }
+1 -1
View File
@@ -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) { pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustCodegen) {
cg.add(&format!( cg.add_indented(&format!(
"{}fn {}{}(", "{}fn {}{}(",
method.visibility.get_rust(), method.visibility.get_rust(),
method.name.get_rust(), method.name.get_rust(),
+29 -13
View File
@@ -3,7 +3,12 @@ pub mod expr;
pub mod statement; pub mod statement;
pub mod top_level; pub mod top_level;
use mist_parser::ast::*; use std::path::PathBuf;
use mist_parser::{
ast::*,
rev_mapper::{Mapping, MistMap, RustMap},
};
pub struct Context { pub struct Context {
pub expr_ensure_semicolon: bool, pub expr_ensure_semicolon: bool,
@@ -22,17 +27,20 @@ pub trait GetRust {
} }
} }
#[derive(Default)]
pub struct RustCodegen { pub struct RustCodegen {
output: String, output: String,
indent: usize, indent: usize,
pub mapping: Mapping,
position: RustMap,
} }
impl RustCodegen { impl RustCodegen {
pub fn new() -> Self { pub fn new(mist_path: PathBuf) -> Self {
Self { Self {
output: String::new(), output: String::new(),
indent: 0, indent: 0,
mapping: Mapping::new(mist_path),
position: RustMap(1, 0),
} }
} }
@@ -41,6 +49,17 @@ impl RustCodegen {
} }
fn add(&mut self, s: &str) { 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); self.output.push_str(s);
} }
@@ -123,21 +142,18 @@ impl GenRust for Attribute {
} }
} }
impl<T: GetRust> GetRust for Spanned<T> { impl<T: GetRust> GenRust for T {
fn get_rust(&self) -> String { fn gen_rust(&self, _: &mut Context, cg: &mut RustCodegen) {
format!( cg.add(&self.get_rust());
"/* {}:{} */ {}",
self.line,
self.column,
self.item.get_rust()
)
} }
} }
impl<T: GenRust> GenRust for Spanned<T> { impl<T: GenRust> GenRust for Spanned<T> {
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column)); cg.mapping
cg.add_indented(""); .map
.insert((cg.position, MistMap(self.line, self.column)));
self.item.gen_rust(ctx, cg); self.item.gen_rust(ctx, cg);
} }
} }
+2
View File
@@ -11,12 +11,14 @@ impl GenRust for Block {
for stmt in &self.statements { for stmt in &self.statements {
ctx.expr_ensure_semicolon = true; ctx.expr_ensure_semicolon = true;
cg.add_indented("");
stmt.gen_rust(ctx, cg); stmt.gen_rust(ctx, cg);
cg.addln(""); cg.addln("");
} }
if let Some(soft_return) = &self.soft_return { if let Some(soft_return) = &self.soft_return {
ctx.expr_ensure_semicolon = false; ctx.expr_ensure_semicolon = false;
cg.add_indented("");
soft_return.gen_rust(ctx, cg); soft_return.gen_rust(ctx, cg);
cg.addln(""); cg.addln("");
} }
+9 -4
View File
@@ -73,7 +73,7 @@ impl GenRust for ImplDecl {
impl GenRust for FunctionDecl { impl GenRust for FunctionDecl {
fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
cg.add(&format!( cg.add_indented(&format!(
"{}fn {}{}(", "{}fn {}{}(",
self.visibility.get_rust(), self.visibility.get_rust(),
self.name.get_rust(), self.name.get_rust(),
@@ -97,8 +97,9 @@ impl GenRust for FunctionDecl {
if let Some(body) = &self.body { if let Some(body) = &self.body {
cg.add(" "); cg.add(" ");
body.gen_rust(ctx, cg); body.gen_rust(ctx, cg);
cg.addln("");
} else { } else {
cg.add(";"); cg.addln(";");
} }
} }
} }
@@ -195,7 +196,9 @@ impl GenRust for TopLevelKind {
cg.indent += 1; cg.indent += 1;
for field in fields { for field in fields {
cg.add_indentedln(&field.get_rust()); cg.add_indented("");
field.gen_rust(ctx, cg);
cg.addln("");
} }
cg.indent -= 1; cg.indent -= 1;
@@ -216,7 +219,9 @@ impl GenRust for TopLevelKind {
cg.indent += 1; cg.indent += 1;
for field in fields { for field in fields {
cg.add_indentedln(&(field.get_rust() + ",")); cg.add_indented("");
field.gen_rust(ctx, cg);
cg.addln(",");
} }
cg.indent -= 1; cg.indent -= 1;
+13 -26
View File
@@ -1,9 +1,7 @@
pub module builder; pub module builder;
use std::collections::HashMap; use std::collections::HashMap;
use std::env;
use std::fs; use std::fs;
use std::path::MAIN_SEPARATOR;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use std::process::Stdio; use std::process::Stdio;
@@ -31,8 +29,6 @@ pub fn build(mut args Vec<String>, root PathBuf) bool {
args.remove(0); args.remove(0);
args.insert(1, "--message-format=json".to_string()); 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") let mut command = Command::new("cargo")
.args(args) .args(args)
.stdout(Stdio::piped()) .stdout(Stdio::piped())
@@ -47,8 +43,6 @@ pub fn build(mut args Vec<String>, root PathBuf) bool {
let mut mapping = HashMap::new(); let mut mapping = HashMap::new();
let mist_src = format!(".mist{MAIN_SEPARATOR}src");
for message in cargo_metadata::Message::parse_stream(&mut reader) { for message in cargo_metadata::Message::parse_stream(&mut reader) {
match message { match message {
Ok[Message::CompilerMessage[msg]] => { Ok[Message::CompilerMessage[msg]] => {
@@ -56,29 +50,23 @@ pub fn build(mut args Vec<String>, root PathBuf) bool {
if span.is_primary { if span.is_primary {
let rust_path = root.join(&span.file_name); let rust_path = root.join(&span.file_name);
let mist_file = span let mapping_path = rust_path.with_extension("map.json");
.file_name
.replacen(&mist_src, "src", 1)
.trim_end_matches(".rs")
.to_string()
+ ".mist";
let mist_path = root.join(&mist_file); if !fs::exists(&mapping_path).expect("Unable to check if map file exists") {
if !fs::exists(&mist_path).expect("Unable to check if mist file exists") {
diagnostics.push(MistDiagnostic::Rust(msg)); diagnostics.push(MistDiagnostic::Rust(msg));
break; break;
} }
let map = mapping.entry(rust_path.clone()).or_insert_with(fn() { let map = mapping.entry(mapping_path.clone()).or_insert_with(fn() {
rev_mapper::get_mapping( let map_str = fs::read_to_string(mapping_path).expect("Failed to read map file");
&fs::read_to_string(rust_path)
.expect("Failed to read file for mapping") serde_json::from_str<rev_mapper::Mapping>(&map_str).expect("Failed to parse map file")
)
}); });
let mist_file = map.mist_path.strip_prefix(&root);
let [_, rev_mapper::MistMap[line, column]] = 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"); .expect("Unable to find mapping");
let mist_msg = MistDiagnosticMessage { let mist_msg = MistDiagnosticMessage {
@@ -87,13 +75,12 @@ pub fn build(mut args Vec<String>, root PathBuf) bool {
msg.message.message, msg.message.message,
span.label.clone().unwrap_or_default() span.label.clone().unwrap_or_default()
), ),
file_name: if is_root { file_name: if let Ok(mist_file) = mist_file {
(); // TODO: fix this mist_file.to_string_lossy().to_string()
mist_file
} else { } 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, line: line,
column: column column: column
}; };
+18 -2
View File
@@ -200,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) { let parsed = match mist_parser::parse(source) {
Ok[ast] => ast; Ok[ast] => ast;
@@ -238,13 +238,29 @@ fn transpile_file(path *PathBuf, source *str, mut output_file PathBuf, mod_decl
let res = fs::write(&output_file, format!("{mod_decl}{output}")); let res = fs::write(&output_file, format!("{mod_decl}{output}"));
gc.mapping.shift_rust(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());
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() { if res.is_err() {
eprintln!( eprintln!(
"error: failed to write output {}\n {}", "error: failed to write output {}\n {}",
output_file.display(), output_file.display(),
res.unwrap_err(), res.as_ref().unwrap_err(),
); );
}
if res_map.is_err() || res.is_err() {
process::exit(1); process::exit(1);
} }
} }
+57 -38
View File
@@ -1,51 +1,70 @@
use std::collections::HashSet; use std::{collections::HashSet, path::PathBuf};
use pest::Parser; use serde::{Deserialize, Serialize};
use pest_derive::Parser;
#[derive(Parser)] #[derive(
#[grammar = "./src/rev_mapper/grammar.pest"] Debug, Default, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
pub struct MistMapperParser; )]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct MistMap(pub usize, pub usize); 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 struct RustMap(pub usize, pub usize);
pub fn get_mapping(input: &str) -> HashSet<(RustMap, MistMap)> { #[derive(Debug, Clone, Serialize, Deserialize)]
let mut mapping = HashSet::new(); pub struct Mapping {
pub mist_path: PathBuf,
let pairs = MistMapperParser::parse(Rule::mapping, input) pub map: HashSet<(RustMap, MistMap)>,
.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( impl Mapping {
mapping: &HashSet<(RustMap, MistMap)>, pub fn new(mist_path: PathBuf) -> Self {
target: &RustMap, Self {
) -> Option<(RustMap, MistMap)> { mist_path,
mapping map: HashSet::new(),
}
}
pub fn find(&self, target: &RustMap) -> Option<(RustMap, MistMap)> {
self.map
.iter() .iter()
.copied() .copied()
.filter(|(rust, _)| rust <= target) .filter(|(rust, _)| rust <= target)
.max_by_key(|(rust, _)| *rust) .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 {
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),
)
}
} }