diff --git a/README.md b/README.md index 65880d9..36c69a7 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ The `div` reduces the vertical height. The `picture` prevents autolinking. **Fast and works with Rust** -- All of your favourite Rust libraries work with Mist +- All of your favorite Rust libraries work with Mist - Compiles directly into efficient Rust code - Zero-cost abstractions, no runtime overhead diff --git a/code.png b/code.png index 771f05d..d08de61 100644 Binary files a/code.png and b/code.png differ diff --git a/crates/analyzer/src/transpiler.rs b/crates/analyzer/src/transpiler.rs index 581ae12..cf0807c 100644 --- a/crates/analyzer/src/transpiler.rs +++ b/crates/analyzer/src/transpiler.rs @@ -1,8 +1,8 @@ use std::path::{Path, PathBuf}; use mist_codegen::RustCodegen; -use mist_parser::rev_mapper::Mapping; use mist_parser::parse; +use mist_parser::rev_mapper::Mapping; pub struct TranspiledFile { pub mist_path: PathBuf, @@ -26,20 +26,23 @@ pub fn transpile_mist( let parsed = parse(source).map_err(|e| format!("parse error: {e:?}"))?; - for item in &parsed { + for item in &parsed.items { mist_parser::semantics::check_class_semantics(item) .map_err(|e| format!("semantic error: {}", e[0].error_message))?; } let mut codegen = RustCodegen::new(mist_path.to_path_buf()); - let output = codegen.generate(parsed); - codegen.mapping.shift_rust(extra_mod_decl.lines().count() as isize, 0); + codegen.generate(parsed.mod_attributes); + + codegen.add(extra_mod_decl); + + let output = codegen.generate(parsed.items); Ok(TranspiledFile { mist_path: mist_path.to_path_buf(), rust_path, - rust_content: format!("{}{}", extra_mod_decl, output), + rust_content: output, mapping: codegen.mapping, }) } diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 7c806f4..83217fb 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -48,7 +48,7 @@ impl RustCodegen { " ".repeat(self.indent) } - fn add(&mut self, s: &str) { + pub fn add(&mut self, s: &str) { let newline_count = bytecount::count(s.as_bytes(), b'\n'); if newline_count == 0 { @@ -63,17 +63,17 @@ impl RustCodegen { self.output.push_str(s); } - fn addln(&mut self, s: &str) { + pub fn addln(&mut self, s: &str) { self.add(s); self.add("\n"); } - fn add_indented(&mut self, s: &str) { + pub fn add_indented(&mut self, s: &str) { let line = format!("{}{}", self.indent_str(), s); self.add(&line); } - fn add_indentedln(&mut self, s: &str) { + pub fn add_indentedln(&mut self, s: &str) { let line = format!("{}{}\n", self.indent_str(), s); self.add(&line); } diff --git a/crates/mist-api/src/builder.mist b/crates/mist-api/src/builder.mist index 4a055aa..6571786 100644 --- a/crates/mist-api/src/builder.mist +++ b/crates/mist-api/src/builder.mist @@ -11,11 +11,11 @@ use mist_parser::rev_mapper; #[derive(Debug, Clone)] pub struct MistDiagnosticMessage { - pub message String, - pub file_path PathBuf, - pub file_name String , - pub line usize, - pub column usize, + pub String message, + pub PathBuf file_path, + pub String file_name, + pub usize line, + pub usize column, } #[derive(Debug, Clone)] @@ -25,7 +25,7 @@ pub enum MistDiagnostic { Rust(CompilerMessage), } -pub fn bool build(mut args Vec, root PathBuf) { +pub bool build(Vec mut args, PathBuf root) { args.remove(0); args.insert(1, "--message-format=json".to_string()); @@ -57,7 +57,7 @@ pub fn bool build(mut args Vec, root PathBuf) { break; } - let map = mapping.entry(mapping_path.clone()).or_insert_with(fn() { + let map = mapping.entry(mapping_path.clone()).or_insert_with(() => { 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") @@ -107,7 +107,7 @@ pub fn bool build(mut args Vec, root PathBuf) { let mut stdout = std::io::stdout(); std::io::copy(&mut raw_reader, &mut stdout) - .map_err(fn(v) -> v.to_string()) + .map_err((v) => v.to_string()) .expect("(Mist) Failed to copy IO"); command.wait().unwrap(); @@ -123,7 +123,7 @@ pub fn bool build(mut args Vec, root PathBuf) { false } -pub fn void print_diagnostics(diagnostics *Vec) { +pub void print_diagnostics(Vec& diagnostics) { let mut files = HashMap::new(); for diag in diagnostics { @@ -159,13 +159,13 @@ pub fn void print_diagnostics(diagnostics *Vec) { } } -pub fn Option get_line( - files *mut HashMap>, - msg *MistDiagnosticMessage, +pub Option get_line( + HashMap> mut& files, + MistDiagnosticMessage& msg, ) { let src_path = msg.file_path.clone(); - let lines = files.entry(src_path.clone()).or_insert_with(fn() { + let lines = files.entry(src_path.clone()).or_insert_with(() => { fs::read_to_string(src_path) .expect("Unable to read mist file") .lines() @@ -174,5 +174,5 @@ pub fn Option get_line( .collect() }); - lines.get(msg.line - 1).map(fn(v) -> v.trim().to_string()) + lines.get(msg.line - 1).map((v) => v.trim().to_string()) } diff --git a/crates/mist-api/src/modules.mist b/crates/mist-api/src/modules.mist index 6754844..af7b8b3 100644 --- a/crates/mist-api/src/modules.mist +++ b/crates/mist-api/src/modules.mist @@ -9,14 +9,14 @@ use crate::transpiler::MistConfig; #[derive(Debug)] pub class Module { - pub name String; - pub path PathBuf; - pub children Vec; + pub String name; + pub PathBuf path; + pub Vec children; - pub constructor(mist_path PathBuf, config *MistConfig) { + pub constructor(PathBuf mist_path, MistConfig& config) { self.children = Vec::new(); self.name = mist_path.file_stem() - .and_then(fn(s) -> s.to_str()) + .and_then((s) => s.to_str()) .expect("Failed to get module name") .to_string(); self.path = mist_path; @@ -37,7 +37,7 @@ pub class Module { } } - fn void scan_directory(*mut self, search_dir *Path, config *MistConfig) { + void scan_directory(&mut self, Path& search_dir, MistConfig& config) { let entries = match fs::read_dir(search_dir) { Ok(entries) => entries; Err(e) => { @@ -65,11 +65,11 @@ pub class Module { } } - pub fn bool is_package(*self) { - self.path.file_name().map(fn(v) -> v.to_str()).unwrap_or_default() == Some("package.mist") + pub bool is_package(&self) { + self.path.file_name().map((v) => v.to_str()).unwrap_or_default() == Some("package.mist") } - pub fn PathBuf output_dir(*self, parent_dir *PathBuf) { + pub PathBuf output_dir(&self, PathBuf& parent_dir) { if self.path.is_dir() || self.is_package() { parent_dir.join(&self.name) } else { @@ -77,7 +77,13 @@ pub class Module { } } - pub fn PathBuf output_path(*self, parent_dir *PathBuf, curr_mod_decl *Option<(mist_parser::ast::Visibility, mist_parser::ast::Identifier)>) { + pub PathBuf output_path(&self, + PathBuf& parent_dir, + Option<( + mist_parser::ast::Visibility, + mist_parser::ast::Identifier + )>& curr_mod_decl + ) { let name = if let Some((_, name)) = curr_mod_decl { &name.0 } else { diff --git a/crates/mist-api/src/transpiler.mist b/crates/mist-api/src/transpiler.mist index 5bbed65..5b6ce8d 100644 --- a/crates/mist-api/src/transpiler.mist +++ b/crates/mist-api/src/transpiler.mist @@ -16,13 +16,13 @@ use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(default)] pub struct MistConfig { - pub package PathBuf, - pub packages Vec, - pub main_mods String + pub PathBuf package, + pub Vec packages, + pub String main_mods } impl MistConfig { - pub fn bool should_ignore(*self, path *Path) { + pub bool should_ignore(&self, Path& path) { if path == self.package { return true; } @@ -37,7 +37,7 @@ impl MistConfig { } } impl Default for MistConfig { - fn Self default() { + Self default() { Self { package: PathBuf::from("main.mist"), packages: Vec::new(), @@ -46,7 +46,7 @@ impl Default for MistConfig { } } -pub fn PathBuf transpile() { +pub PathBuf transpile() { let start = time::Instant::now(); let root = env::current_dir().expect("Unable to find project root"); @@ -56,10 +56,10 @@ pub fn PathBuf transpile() { let out = root.join(".mist/src"); let toml_content = fs::read_to_string(&toml_path) - .unwrap_or_else(fn(_) -> panic!("Could not read file at {:?}", toml_path)); + .unwrap_or_else((_) => panic!("Could not read file at {:?}", toml_path)); - let mut config MistConfig = toml::from_str(&toml_content) - .unwrap_or_else(fn(_) -> panic!("Failed to parse Mist.toml from {:?}", toml_path)); + MistConfig mut config = toml::from_str(&toml_content) + .unwrap_or_else((_) => panic!("Failed to parse Mist.toml from {:?}", toml_path)); for pkg in &mut config.packages { *pkg = src.join(&*pkg); @@ -85,10 +85,10 @@ pub fn PathBuf transpile() { } impl modules::Module { - fn (bool, String) transpile(*self, parent_dir *PathBuf, config *mut MistConfig) { - if !self.path.is_dir() && self.path.extension().and_then(fn(v) -> v.to_str()) != Some("mist") { + (bool, String) transpile(&self, PathBuf& parent_dir, MistConfig mut& config) { + if !self.path.is_dir() && self.path.extension().and_then((v) => v.to_str()) != Some("mist") { let file_name = self.path.file_name() - .and_then(fn(s) -> s.to_str()) + .and_then((s) => s.to_str()) .expect("Failed to get file name"); fs::copy(&self.path, parent_dir.join(&file_name)).expect("Failed to copy SideFile"); @@ -124,7 +124,7 @@ impl modules::Module { self.write_transpile(output, parent_dir, child_changed) } - fn (bool, String) write_transpile(*self, output String, parent_dir *PathBuf, child_changed bool) { + (bool, String) write_transpile(&self, String output, PathBuf& parent_dir, bool child_changed) { if self.path.is_dir() { let output_file = self.output_path(parent_dir, &None); @@ -174,7 +174,7 @@ impl modules::Module { } } -fn std::io::Result is_source_newer(source *Path, output *Path) { +std::io::Result is_source_newer(Path& source, Path& output) { if !output.exists() { return Ok(true); } @@ -190,12 +190,18 @@ pub enum TranspileError<'a> { Semantic(Vec) } -pub fn Result<(PathBuf, mist_codegen::RustCodegen, String), TranspileError<'a>> - transpile_code<'a>(path *PathBuf, source *'a str, mut output_file PathBuf, mod_decl *str, curr_mod_decl *Option<(mist_parser::ast::Visibility, mist_parser::ast::Identifier)>) { +pub Result<(PathBuf, mist_codegen::RustCodegen, String), TranspileError<'a>> + transpile_code<'a>( + PathBuf& path, + str 'a& source, + PathBuf mut output_file, + str& mod_decl, + Option<(mist_parser::ast::Visibility, mist_parser::ast::Identifier)>& curr_mod_decl + ) { if let Some((_, name)) = &curr_mod_decl { - if output_file.file_name().map(fn(v) -> v.to_str()).unwrap_or_default() != Some("mod.rs") { - if let Some(ext) = output_file.extension().map(fn(e) -> e.to_owned()) { + if output_file.file_name().map((v) => v.to_str()).unwrap_or_default() != Some("mod.rs") { + if let Some(ext) = output_file.extension().map((e) => e.to_owned()) { let mut new_name = std::ffi::OsString::from(&name.0); new_name.push("."); @@ -212,18 +218,27 @@ pub fn Result<(PathBuf, mist_codegen::RustCodegen, String), TranspileError<'a>> let parsed = mist_parser::parse(source).map_err(TranspileError::Parse)?; - for i in &parsed { + for i in &parsed.items { let _ = mist_parser::semantics::check_class_semantics(i).map_err(TranspileError::Semantic)?; } - let output = gc.generate(parsed); + gc.generate(parsed.mod_attributes); - gc.mapping.shift_rust(mod_decl.lines().count() as isize, 0); + gc.add(mod_decl); + + let output = gc.generate(parsed.items); Ok((output_file, gc, output)) } -pub fn void transpile_file(path *PathBuf, source *str, output_file PathBuf, mod_decl *str, curr_mod_decl *Option<(mist_parser::ast::Visibility, mist_parser::ast::Identifier)>) { +pub void transpile_file( + PathBuf& path, + str& source, + PathBuf output_file, + str& mod_decl, + Option<(mist_parser::ast::Visibility, mist_parser::ast::Identifier)>& curr_mod_decl + ) { + let (output_file, gc, output) = match transpile_code(path, source, output_file, mod_decl, curr_mod_decl) { Ok(output) => output; Err(e) => { @@ -232,7 +247,7 @@ pub fn void transpile_file(path *PathBuf, source *str, output_file PathBuf, mod_ } }; - let res = fs::write(&output_file, format!("{mod_decl}{output}")); + let res = fs::write(&output_file, output); let output_file_map = output_file.with_extension("map.json"); @@ -259,7 +274,7 @@ pub fn void transpile_file(path *PathBuf, source *str, output_file PathBuf, mod_ } } -pub fn void decode_err<'a>(err *TranspileError<'a>, path *PathBuf) { +pub void decode_err<'a>(TranspileError<'a>& err, PathBuf& path) { let curr_dir = std::env::current_dir().unwrap(); match err { diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 561c979..719e55d 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -30,7 +30,6 @@ keyword = { | "false" | "dyn" | "loop" - | "fn" | "unsafe" | "override" } @@ -82,7 +81,7 @@ module_program = { visibility = { "pub" ~ ("(" ~ static_path ~ ")")? } mutable = { "mut" } -unsafe_kw = { "unsafe" } +unsafe_kw = { "unsafe" } // ====================================================== // GENERICS @@ -108,7 +107,7 @@ path_type = { ref_lifetime = { lifetime | unsafe_kw } ref_type = { - "*" ~ ref_lifetime? ~ mutable? ~ type_expr + mutable? ~ ref_lifetime? ~ "&" } dyn_type = { @@ -116,7 +115,7 @@ dyn_type = { } type_expr = { - (path_type | tuple_type | ref_type | dyn_type) + (path_type | tuple_type | dyn_type) ~ ref_type* } lifetime = { @@ -200,15 +199,17 @@ attributes = { // DECLARATION HELPERS // ====================================================== var_decl = { - "let" ~ pattern ~ type_expr? + ("let" ~ pattern) + | type_expr ~ (!tuple_pattern ~ pattern) } field = { - visibility? ~ identifier ~ type_expr + visibility? ~ type_expr ~ identifier } param = { - pattern ~ type_expr? + (type_expr ~ pattern) + | pattern } field_list = { @@ -286,7 +287,7 @@ class_field = { } self_param = { - (deref_px ~ lifetime?)? ~ mutable? ~ "self" + (ref_px ~ lifetime?)? ~ mutable? ~ "self" } method_args = _{ @@ -333,7 +334,7 @@ trait_decl = { override_kw = { "override" ~ ("(" ~ expr_path ~ ")")? } function_decl = { - visibility? ~ "fn" ~ ("void" | type_expr) ~ identifier ~ generics_decl? ~ "(" ~ method_args ~ ")" ~ override_kw? ~ (block | semicolon) + visibility? ~ ("void" | type_expr) ~ identifier ~ generics_decl? ~ "(" ~ method_args ~ ")" ~ override_kw? ~ (block | semicolon) } // ====================================================== @@ -341,8 +342,8 @@ function_decl = { // ====================================================== top_level = { - (attributes ~ (import | impl_for_decl | impl_decl | trait_decl | struct_decl | enum_decl | class_decl | declare_module | function_decl)) - | mod_attribute + mod_attribute + | (attributes ~ (import | impl_for_decl | impl_decl | trait_decl | struct_decl | enum_decl | class_decl | declare_module | function_decl)) } // ====================================================== @@ -449,7 +450,7 @@ loop_stmt = { pattern_list = { pattern ~ ("|" ~ pattern)* } match_item = { - pattern_list ~ "=>" ~ statement + pattern_list ~ "=>" ~ (statement | (expr ~ ",")) } match_stmt = { @@ -465,8 +466,8 @@ match_stmt = { // ------------------------------------------------------ closure = { - "fn" ~ "(" ~ param_list ~ ")" ~ type_expr? ~ block - | "fn" ~ "(" ~ param_list ~ ")" ~ type_expr? ~ "->" ~ expr + ("(" ~ param_list ~ ")" ~ "=>" ~ expr) + | (type_expr ~ "(" ~ param_list ~ ")" ~ "=>" ~ expr) } // ------------------------------------------------------ diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index cf905f0..7c6a1d1 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -15,7 +15,12 @@ use crate::error::{IntoErr, ParseError}; #[grammar = "./src/grammar.pest"] pub struct MistParser; -pub fn parse<'a>(source: &'a str) -> Result, ParseError<'a, Vec>> { +pub struct Program { + pub mod_attributes: Vec, + pub items: Vec, +} + +pub fn parse<'a>(source: &'a str) -> Result>> { let mut pairs = MistParser::parse(Rule::program, source)?; let mut statements = vec![]; @@ -29,7 +34,16 @@ pub fn parse<'a>(source: &'a str) -> Result, ParseError<'a, Vec Ok(v), + Ok(v) => { + let (mod_attributes, items): (Vec<_>, Vec<_>) = v + .into_iter() + .partition(|item| matches!(item.0.item, TopLevelKind::ModAttribute)); + + Ok(Program { + items, + mod_attributes, + }) + } Err(e) => { let rec = e.recovered.clone(); diff --git a/crates/parser/src/parser/common/decl.rs b/crates/parser/src/parser/common/decl.rs index 7a07fb9..acf076d 100644 --- a/crates/parser/src/parser/common/decl.rs +++ b/crates/parser/src/parser/common/decl.rs @@ -3,6 +3,7 @@ use crate::{ ast::*, ast_expr, error::{AstError, IntoErr, collect_recovered}, + parser::consume_rule, }; impl<'a> TryFrom> for VarDeclStmt { @@ -52,8 +53,10 @@ impl<'a> TryFrom> for VarDecl { let mut inner = pair.into_inner(); ast_expr!(VarDecl { + type_: consume_rule(&mut inner, Rule::type_expr) + .map(TypeExpr::try_from) + .transpose(), name: Pattern::try_from(inner.next().unwrap()), - type_: inner.next().map(TypeExpr::try_from).transpose(), }) } @@ -72,8 +75,8 @@ impl<'a> TryFrom> for FieldDecl { ast_expr!(FieldDecl { visibility: Visibility::try_from(&mut inner), - name: Identifier::try_from(inner.next().unwrap()), type_: TypeExpr::try_from(inner.next().unwrap()), + name: Identifier::try_from(inner.next().unwrap()), }) } diff --git a/crates/parser/src/parser/common/expr.rs b/crates/parser/src/parser/common/expr.rs index 01ae58b..5f4afa6 100644 --- a/crates/parser/src/parser/common/expr.rs +++ b/crates/parser/src/parser/common/expr.rs @@ -77,10 +77,10 @@ impl<'a> TryFrom> for Expression { Rule::closure => { ast_expr!(Expression::Closure { - params: collect_recovered(inner.next().unwrap().into_inner()), return_type: consume_rule(&mut inner, Rule::type_expr) .map(TypeExpr::try_from) .transpose(), + params: collect_recovered(inner.next().unwrap().into_inner()), body: Expression::try_from(inner.next().unwrap()).map(Box::new), }) } diff --git a/crates/parser/src/parser/common/types.rs b/crates/parser/src/parser/common/types.rs index 3d2fa2b..54d749d 100644 --- a/crates/parser/src/parser/common/types.rs +++ b/crates/parser/src/parser/common/types.rs @@ -2,7 +2,7 @@ use crate::{ Rule, ast::*, ast_ensure, ast_expr, - error::{AstError, AstResult, IntoErr, collect_recovered}, + error::{AstError, IntoErr, collect_recovered}, parser::{consume_rule, listen_rule}, }; @@ -15,7 +15,27 @@ impl<'a> TryFrom> for TypeExpr { match rule { Rule::generic => Self::try_from(inner.next().unwrap()), - Rule::type_expr => inner.next().unwrap().try_into(), + Rule::type_expr => { + let mut inner = inner; + + let mut ty = TypeExpr::try_from(inner.next().unwrap())?; + + for ref_pair in inner { + let mut ref_inner = ref_pair.into_inner(); + + ty = TypeExpr::Ref { + lifetime: consume_rule(&mut ref_inner, Rule::ref_lifetime) + .map(|v| v.into_inner().next().map(Lifetime::try_from)) + .unwrap_or_default() + .transpose() + .get()?, + mutable: listen_rule(&mut ref_inner, Rule::mutable), + ty: Box::new(ty), + }; + } + + Ok(ty) + } Rule::lifetime => ast_expr!(TypeExpr::Lifetime(inner.next().unwrap().try_into())), Rule::tuple_type => ast_expr!(TypeExpr::Tuple(collect_recovered(inner))), @@ -26,16 +46,6 @@ impl<'a> TryFrom> for TypeExpr { )) } - Rule::ref_type => { - ast_expr!(TypeExpr::Ref { - lifetime: consume_rule(&mut inner, Rule::ref_lifetime) - .map(|v| v.into_inner().next().map(Lifetime::try_from)) - .unwrap_or_default() - .transpose(), - mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult, - ty: TypeExpr::try_from(inner.next().unwrap()).map(Box::new), - }) - } Rule::dyn_type => { ast_expr!(TypeExpr::Dyn( TypeExpr::try_from(inner.next().unwrap()).map(Box::new), diff --git a/crates/parser/src/parser/items/function.rs b/crates/parser/src/parser/items/function.rs index 10b519e..2bac071 100644 --- a/crates/parser/src/parser/items/function.rs +++ b/crates/parser/src/parser/items/function.rs @@ -27,7 +27,7 @@ impl<'a> TryFrom> for FunctionDecl { let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { let mut param_inner = param.into_inner(); - let is_ref = listen_rule(&mut param_inner, Rule::deref_px); + let is_ref = listen_rule(&mut param_inner, Rule::ref_px); let lifetime = consume_rule(&mut param_inner, Rule::lifetime); let mutable = listen_rule(&mut param_inner, Rule::mutable); let name = Pattern::Path(mutable && !is_ref, Path(vec![Identifier(String::from("self"))])); diff --git a/crates/parser/src/parser/items/mod.rs b/crates/parser/src/parser/items/mod.rs index 1bae6d0..ab4600b 100644 --- a/crates/parser/src/parser/items/mod.rs +++ b/crates/parser/src/parser/items/mod.rs @@ -16,12 +16,15 @@ impl<'a> TryFrom> for TopLevel { type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let mut inner = pair.into_inner(); + let mut inner = pair.clone().into_inner(); let attributes = collect_recovered(inner.next().unwrap().into_inner()); ast_expr!(TopLevel( - inner.next().map(Spanned::try_from).unwrap(), + inner + .next() + .map(Spanned::try_from) + .unwrap_or_else(move || Ok(Spanned::new_pair(pair, TopLevelKind::ModAttribute))), attributes, )) } diff --git a/crates/parser/src/parser/mod.rs b/crates/parser/src/parser/mod.rs index 2e73885..6662791 100644 --- a/crates/parser/src/parser/mod.rs +++ b/crates/parser/src/parser/mod.rs @@ -28,6 +28,18 @@ pub fn consume_rule<'a>( if consumed { pairs.next() } else { None } } +impl Spanned { + fn new_pair(pair: pest::iterators::Pair<'_, Rule>, item: T) -> Self { + let span = pair.as_span().start_pos().line_col(); + + Self { + line: span.0, + column: span.1, + item, + } + } +} + impl<'a, T: TryFrom, Error = AstError<'a, T>>> TryFrom> for Spanned { diff --git a/mist-test/src/common/decl_test.mist b/mist-test/src/common/decl_test.mist index d1a1688..57a8717 100644 --- a/mist-test/src/common/decl_test.mist +++ b/mist-test/src/common/decl_test.mist @@ -1,44 +1,44 @@ pub module decl_test; -pub fn void test_let_basic() { +pub void test_let_basic() { let x = 42; assert_eq!(x, 42); } -pub fn void test_let_typed() { - let x i32 = 42; +pub void test_let_typed() { + i32 x = 42; assert_eq!(x, 42); - let s *str = "hello"; + str& s = "hello"; assert_eq!(s, "hello"); - let b bool = true; + bool b = true; assert_eq!(b, true); - let f f64 = 3.14; + f64 f = 3.14; assert_eq!(f, 3.14); } -pub fn void test_let_mut() { +pub void test_let_mut() { let mut _x = 42; _x = 100; assert_eq!(_x, 100); } -pub fn void test_let_tuple_destructure() { +pub void test_let_tuple_destructure() { let (a, b) = (10, "hello"); assert_eq!(a, 10); assert_eq!(b, "hello"); } -pub fn void test_let_nested_tuple() { +pub void test_let_nested_tuple() { let (a, (b, c)) = (1, (2, 3)); assert_eq!(a, 1); assert_eq!(b, 2); assert_eq!(c, 3); } -pub fn void test_let_pattern_irrefutable() { +pub void test_let_pattern_irrefutable() { let x = 5; let (y, z) = (1, 2); assert_eq!(x, 5); @@ -46,30 +46,30 @@ pub fn void test_let_pattern_irrefutable() { assert_eq!(z, 2); } -pub fn void test_multiple_decls() { +pub void test_multiple_decls() { let a = 1; let b = 2; let c = 3; assert_eq!(a + b + c, 6); } -pub fn void test_let_with_type_and_init() { - let x f64 = 10.0; +pub void test_let_with_type_and_init() { + f64 x = 10.0; assert_eq!(x, 10.0); } -pub fn void test_string_literal() { +pub void test_string_literal() { let s = "hello, world!"; assert_eq!(s.len(), 13); } -pub fn void test_let_bool() { +pub void test_let_bool() { let t = true; let f = false; assert_eq!(t, !f); } -pub fn void run_tests() { +pub void run_tests() { test_let_basic(); test_let_typed(); test_let_mut(); diff --git a/mist-test/src/common/expr_test.mist b/mist-test/src/common/expr_test.mist index 88ab9b3..c344a00 100644 --- a/mist-test/src/common/expr_test.mist +++ b/mist-test/src/common/expr_test.mist @@ -1,6 +1,6 @@ pub module expr_test; -pub fn void test_literals() { +pub void test_literals() { assert_eq!(42, 42); assert_eq!(3.14, 3.14); assert_eq!(true, true); @@ -8,28 +8,28 @@ pub fn void test_literals() { assert_eq!("hello", "hello"); } -pub fn void test_tuples() { +pub void test_tuples() { let t = (1, true, "three"); assert_eq!(t.0, 1); assert_eq!(t.1, true); assert_eq!(t.2, "three"); } -pub fn void test_arrays() { +pub void test_arrays() { let arr = [1, 2, 3]; assert_eq!(arr[0], 1); assert_eq!(arr[1], 2); assert_eq!(arr[2], 3); } -pub fn void test_array_repeat() { +pub void test_array_repeat() { let arr = [0; 5]; assert_eq!(arr[0], 0); assert_eq!(arr[4], 0); assert_eq!(arr.len(), 5); } -pub fn void test_binary_arith() { +pub void test_binary_arith() { assert_eq!(10 + 5, 15); assert_eq!(10 - 5, 5); assert_eq!(10 * 5, 50); @@ -37,7 +37,7 @@ pub fn void test_binary_arith() { assert_eq!(10 % 3, 1); } -pub fn void test_binary_cmp() { +pub void test_binary_cmp() { assert_eq!(5 < 10, true); assert_eq!(10 <= 10, true); assert_eq!(10 > 5, true); @@ -46,14 +46,14 @@ pub fn void test_binary_cmp() { assert_eq!(5 != 10, true); } -pub fn void test_binary_logic() { +pub void test_binary_logic() { assert_eq!(true && true, true); assert_eq!(true && false, false); assert_eq!(true || false, true); assert_eq!(false || false, false); } -pub fn void test_binary_bit() { +pub void test_binary_bit() { assert_eq!(5 & 3, 1); assert_eq!(5 | 3, 7); assert_eq!(5 ^ 3, 6); @@ -61,20 +61,20 @@ pub fn void test_binary_bit() { assert_eq!(4 >> 1, 2); } -pub fn void test_prefix() { +pub void test_prefix() { let x = 42; assert_eq!(-x, -42); assert_eq!(!true, false); assert_eq!(!false, true); } -pub fn void test_ref_deref() { +pub void test_ref_deref() { let x = 42; let r = &x; assert_eq!(*r, 42); } -pub fn void test_postfix_inc_dec() { +pub void test_postfix_inc_dec() { let mut x = 5; x++; assert_eq!(x, 6); @@ -82,17 +82,17 @@ pub fn void test_postfix_inc_dec() { assert_eq!(x, 5); } -pub fn void test_as_cast() { +pub void test_as_cast() { let x = 42; assert_eq!(x as f64, 42.0); } -pub fn void test_closure() { - let add = fn(a, b) -> a + b; +pub void test_closure() { + let add = (a, b) => a + b; assert_eq!(add(2, 3), 5); } -pub fn void test_block_expr() { +pub void test_block_expr() { let x = { let y = 10; y + 5 @@ -100,7 +100,7 @@ pub fn void test_block_expr() { assert_eq!(x, 15); } -pub fn void test_if_expr() { +pub void test_if_expr() { let x = if true { 1 } else { 2 }; assert_eq!(x, 1); @@ -108,7 +108,7 @@ pub fn void test_if_expr() { assert_eq!(y, 2); } -pub fn void test_range_expr() { +pub void test_range_expr() { let r = 0..5; let mut count = 0; for i in r { @@ -117,7 +117,7 @@ pub fn void test_range_expr() { assert_eq!(count, 5); } -pub fn void test_binary_assign() { +pub void test_binary_assign() { let mut x = 10; x += 5; assert_eq!(x, 15); @@ -131,7 +131,7 @@ pub fn void test_binary_assign() { assert_eq!(x, 2); } -pub fn void run_tests() { +pub void run_tests() { test_literals(); test_tuples(); test_arrays(); diff --git a/mist-test/src/common/package.mist b/mist-test/src/common/package.mist index 324108d..3fb9503 100644 --- a/mist-test/src/common/package.mist +++ b/mist-test/src/common/package.mist @@ -1,3 +1,3 @@ pub module common; -pub fn void test_package() {} +pub void test_package() {} diff --git a/mist-test/src/common/statement_test.mist b/mist-test/src/common/statement_test.mist index ce9a7e9..00ca939 100644 --- a/mist-test/src/common/statement_test.mist +++ b/mist-test/src/common/statement_test.mist @@ -1,23 +1,23 @@ pub module statement_test; -pub fn void test_var_decl() { +pub void test_var_decl() { let x = 42; assert_eq!(x, 42); - let y i32 = 10; + i32 y = 10; assert_eq!(y, 10); - let name *str = "mist"; + str& name = "mist"; assert_eq!(name, "mist"); } -pub fn void test_var_decl_with_init() { +pub void test_var_decl_with_init() { let mut x = 0; x = 5; assert_eq!(x, 5); } -pub fn void test_if_statement() { +pub void test_if_statement() { let mut x = 0; if true { @@ -33,7 +33,7 @@ pub fn void test_if_statement() { assert_eq!(x, 3); } -pub fn void test_if_else_if() { +pub void test_if_else_if() { let mut x = 0; if x == 1 { @@ -46,7 +46,7 @@ pub fn void test_if_else_if() { assert_eq!(x, 20); } -pub fn void test_while_loop() { +pub void test_while_loop() { let mut count = 0; while count < 5 { @@ -55,7 +55,7 @@ pub fn void test_while_loop() { assert_eq!(count, 5); } -pub fn void test_for_loop() { +pub void test_for_loop() { let mut sum = 0; for i in 0..4 { @@ -64,7 +64,7 @@ pub fn void test_for_loop() { assert_eq!(sum, 6); } -pub fn void test_loop_stmt() { +pub void test_loop_stmt() { let mut count = 0; loop { @@ -76,7 +76,7 @@ pub fn void test_loop_stmt() { assert_eq!(count, 3); } -pub fn void test_break_continue() { +pub void test_break_continue() { let mut sum = 0; for i in 0..10 { @@ -91,11 +91,11 @@ pub fn void test_break_continue() { assert_eq!(sum, 1 + 3 + 5); } -pub fn i32 test_return() { +pub i32 test_return() { return 42; } -pub fn void test_block_scope() { +pub void test_block_scope() { let x = { let inner = 10; inner + 5 @@ -103,22 +103,22 @@ pub fn void test_block_scope() { assert_eq!(x, 15); } -pub fn void test_match_literal() { +pub void test_match_literal() { let x = 2; let result; match x { 1 => { result = 10; } - 2 => { result = 20; } - 3 => { result = 30; } + 2 => result = 20; + 3 => result = 30, _ => panic!(); } assert_eq!(result, 20); } -pub fn void test_match_or_pattern() { +pub void test_match_or_pattern() { let x = 1; - let result i32; + i32 result; match x { 1 | 2 => { result = 100; } @@ -128,7 +128,7 @@ pub fn void test_match_or_pattern() { assert_eq!(result, 100); } -pub fn void test_match_default() { +pub void test_match_default() { let x = 99; let result; @@ -139,7 +139,7 @@ pub fn void test_match_default() { assert_eq!(result, 99); } -pub fn void test_for_with_pattern_destructure() { +pub void test_for_with_pattern_destructure() { let pairs = [(1, "a"), (2, "b")]; let mut keys = 0; @@ -149,7 +149,7 @@ pub fn void test_for_with_pattern_destructure() { assert_eq!(keys, 3); } -pub fn void run_tests() { +pub void run_tests() { test_var_decl(); test_var_decl_with_init(); test_if_statement(); diff --git a/mist-test/src/common/types_test.mist b/mist-test/src/common/types_test.mist index eaf2cf4..59f4f30 100644 --- a/mist-test/src/common/types_test.mist +++ b/mist-test/src/common/types_test.mist @@ -1,58 +1,58 @@ pub module types_test; -pub fn void test_integer_type() { - let x i32 = 42; +pub void test_integer_type() { + i32 x = 42; assert_eq!(x, 42); } -pub fn void test_float_type() { - let x f64 = 3.14; +pub void test_float_type() { + f64 x = 3.14; assert_eq!(x, 3.14); } -pub fn void test_bool_type() { - let x bool = true; +pub void test_bool_type() { + bool x = true; assert_eq!(x, true); - let y bool = false; + bool y = false; assert_eq!(y, false); } -pub fn void test_string_type() { - let s *str = "hello"; +pub void test_string_type() { + str& s = "hello"; assert_eq!(s, "hello"); } -pub fn void test_tuple_type() { - let t (i32, *str) = (42, "answer"); +pub void test_tuple_type() { + (i32, str&) t = (42, "answer"); assert_eq!(t.0, 42); assert_eq!(t.1, "answer"); } -pub fn void test_ref_type() { - let x i32 = 42; - let r *i32 = &x; +pub void test_ref_type() { + i32 x = 42; + i32& r = &x; assert_eq!(*r, 42); } -pub fn void test_mut_ref_type() { +pub void test_mut_ref_type() { let mut x = 42; - let r *mut i32 = &mut x; + i32 mut& r = &mut x; *r = 100; assert_eq!(x, 100); } -pub fn void test_void_type() {} +pub void test_void_type() {} -fn i32 add(a i32, b i32) { +i32 add(i32 a, i32 b) { a + b } -pub fn void test_fn_return_type() { +pub void test_fn_return_type() { assert_eq!(add(3, 4), 7); } -pub fn void run_tests() { +pub void run_tests() { test_integer_type(); test_float_type(); test_bool_type(); diff --git a/mist-test/src/items/attribute_test.mist b/mist-test/src/items/attribute_test.mist index 5363dd1..03dd461 100644 --- a/mist-test/src/items/attribute_test.mist +++ b/mist-test/src/items/attribute_test.mist @@ -2,22 +2,22 @@ pub module attribute_test; #[derive(Debug)] pub struct Debuggable { - value i32, + i32 value, } -pub fn void test_derive_attribute() { +pub void test_derive_attribute() { let d = Debuggable { value: 42 }; assert_eq!(d.value, 42); } #[allow(unused_variables)] -pub fn void test_allow_attribute() { +pub void test_allow_attribute() { let x = 42; let y = "unused"; assert_eq!(x, 42); } -pub fn void run_tests() { +pub void run_tests() { test_derive_attribute(); test_allow_attribute(); } diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index 3d7ab57..1bb6f20 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -1,21 +1,21 @@ pub module class_test; pub class Animal { - pub name String; + pub String name; constructor() { self.name = "Rex".to_string(); } - pub fn String speak(*self) { + pub String speak(&self) { "Unknown".to_string() } - pub fn void test_speak(*self) { + pub void test_speak(&self) { assert_eq!(self.speak(), "Woof!"); } - pub fn void static_method() {} + pub void static_method() {} } pub class Mammal : Animal { @@ -23,7 +23,7 @@ pub class Mammal : Animal { super = Super::new(); } - pub fn void args_test(*self, x i32, y *str) { + pub void args_test(&self, i32 x, str& y) { assert_eq!(x, 10); assert_eq!(y, "hello"); } @@ -34,18 +34,18 @@ pub class Dog : Mammal { super = Super::new(); } - pub fn String speak(*self) override(Animal) { + pub String speak(&self) override(Animal) { "Woof!".to_string() } impl std::fmt::Display { - fn Result<(), std::fmt::Error> fmt(*self, f *mut std::fmt::Formatter<'_>) { + Result<(), std::fmt::Error> fmt(&self, std::fmt::Formatter<'_> mut& f) { write!(f, "🐾 {}", self.name) } } } -pub fn void run_tests() { +pub void run_tests() { let dawg = Dog::new(); dawg.args_test(10, "hello"); diff --git a/mist-test/src/items/enum_test.mist b/mist-test/src/items/enum_test.mist index db6c763..2eafd99 100644 --- a/mist-test/src/items/enum_test.mist +++ b/mist-test/src/items/enum_test.mist @@ -5,7 +5,7 @@ enum OptionInt { Some(i32), } -pub fn void test_enum_named() { +pub void test_enum_named() { let x = OptionInt::None; match x { OptionInt::None => { assert_eq!(1, 1); } @@ -13,7 +13,7 @@ pub fn void test_enum_named() { } } -pub fn void test_enum_tuple() { +pub void test_enum_tuple() { let x = OptionInt::Some(42); match x { OptionInt::None => { assert_eq!(0, 1); } @@ -22,11 +22,11 @@ pub fn void test_enum_tuple() { } enum Shape { - Circle { radius i32 }, - Rect { w i32, h i32 }, + Circle { i32 radius }, + Rect { i32 w, i32 h }, } -pub fn void test_enum_struct() { +pub void test_enum_struct() { let c = Shape::Circle { radius: 5 }; match c { Shape::Circle { radius } => { assert_eq!(radius, 5); } @@ -46,7 +46,7 @@ enum Color { Blue, } -pub fn void test_enum_eq() { +pub void test_enum_eq() { let c = Color::Red; match c { Color::Red => { assert_eq!(1, 1); } @@ -54,7 +54,7 @@ pub fn void test_enum_eq() { } } -pub fn void run_tests() { +pub void run_tests() { test_enum_named(); test_enum_tuple(); test_enum_struct(); diff --git a/mist-test/src/items/function_test.mist b/mist-test/src/items/function_test.mist index 3cec722..a795225 100644 --- a/mist-test/src/items/function_test.mist +++ b/mist-test/src/items/function_test.mist @@ -1,60 +1,60 @@ pub module function_test; -fn void greet() { +void greet() { let mut x = 1; x++; } -pub fn void test_basic_function() { +pub void test_basic_function() { greet(); } -fn i32 add(a i32, b i32) { +i32 add(i32 a, i32 b) { a + b } -pub fn void test_fn_params() { +pub void test_fn_params() { assert_eq!(add(2, 3), 5); } -pub fn i32 test_fn_return() { +pub i32 test_fn_return() { 42 } -pub fn i32 test_fn_early_return() { +pub i32 test_fn_early_return() { return 100; 0 } -pub fn i32 test_fn_mut_param(mut x i32) { +pub i32 test_fn_mut_param(i32 mut x) { x = x + 10; x } -pub fn void test_method_call() { +pub void test_method_call() { let s = "hello"; assert_eq!(s.len(), 5); assert_eq!(s.to_uppercase(), "HELLO"); } -fn i32 triple(x i32) { +i32 triple(i32 x) { add(x, add(x, x)) } -pub fn void test_nested_fn_calls() { +pub void test_nested_fn_calls() { assert_eq!(triple(5), 15); } -fn i32 factorial(n i32) { +i32 factorial(i32 n) { if n <= 1 { 1 } else { n * factorial(n - 1) } } -pub fn void test_recursive_fn() { +pub void test_recursive_fn() { assert_eq!(factorial(5), 120); } -pub fn void run_tests() { +pub void run_tests() { test_basic_function(); test_fn_params(); assert_eq!(test_fn_return(), 42); diff --git a/mist-test/src/items/impl_test.mist b/mist-test/src/items/impl_test.mist index 68d0ed6..36c83ab 100644 --- a/mist-test/src/items/impl_test.mist +++ b/mist-test/src/items/impl_test.mist @@ -1,39 +1,39 @@ pub module impl_test; struct Vector2 { - x i32, - y i32, + i32 x, + i32 y, } impl Vector2 { - pub fn i32 magnitude(*self) { + pub i32 magnitude(&self) { self.x * self.x + self.y * self.y } } -pub fn void test_inherent_impl() { +pub void test_inherent_impl() { let v = Vector2 { x: 3, y: 4 }; assert_eq!(v.magnitude(), 25); } trait Display { - fn String display(*self); + String display(&self); } impl Display for Vector2 { - fn String display(*self) { + String display(&self) { format!("({}, {})", self.x, self.y) } } -pub fn void test_trait_impl_block() { +pub void test_trait_impl_block() { let v = Vector2 { x: 1, y: 2 }; let s = v.display(); assert_eq!(s.len() > 0, true); } impl Vector2 { - pub fn Vector2 add(*self, other Vector2) { + pub Vector2 add(&self, Vector2 other) { Vector2 { x: self.x + other.x, y: self.y + other.y, @@ -41,7 +41,7 @@ impl Vector2 { } } -pub fn void test_multiple_impls() { +pub void test_multiple_impls() { let a = Vector2 { x: 1, y: 2 }; let b = Vector2 { x: 3, y: 4 }; let c = a.add(b); @@ -49,7 +49,7 @@ pub fn void test_multiple_impls() { assert_eq!(c.y, 6); } -pub fn void run_tests() { +pub void run_tests() { test_inherent_impl(); test_trait_impl_block(); test_multiple_impls(); diff --git a/mist-test/src/items/struct_test.mist b/mist-test/src/items/struct_test.mist index d5e27b1..1bb4e3e 100644 --- a/mist-test/src/items/struct_test.mist +++ b/mist-test/src/items/struct_test.mist @@ -1,23 +1,23 @@ pub module struct_test; struct Point { - x i32, - y i32, + i32 x, + i32 y, } -pub fn void test_struct_create_access() { +pub void test_struct_create_access() { let p = Point { x: 10, y: 20 }; assert_eq!(p.x, 10); assert_eq!(p.y, 20); } -pub fn void test_struct_mut_field() { +pub void test_struct_mut_field() { let mut p = Point { x: 1, y: 2 }; p.x = 100; assert_eq!(p.x, 100); } -pub fn void test_struct_destructure() { +pub void test_struct_destructure() { let p = Point { x: 3, y: 4 }; let Point { x, y } = p; assert_eq!(x, 3); @@ -25,11 +25,11 @@ pub fn void test_struct_destructure() { } struct Line { - start Point, - end Point, + Point start, + Point end, } -pub fn void test_struct_nested() { +pub void test_struct_nested() { let l = Line { start: Point { x: 0, y: 0 }, end: Point { x: 5, y: 10 }, @@ -38,7 +38,7 @@ pub fn void test_struct_nested() { assert_eq!(l.end.y, 10); } -pub fn void run_tests() { +pub void run_tests() { test_struct_create_access(); test_struct_mut_field(); test_struct_destructure(); diff --git a/mist-test/src/items/trait_test.mist b/mist-test/src/items/trait_test.mist index 4e7a2bf..6a26325 100644 --- a/mist-test/src/items/trait_test.mist +++ b/mist-test/src/items/trait_test.mist @@ -1,41 +1,41 @@ pub module trait_test; trait Speak { - fn String speak(*self); + String speak(&self); } trait Greet : Speak { - fn String greet(*self); + String greet(&self); } struct Dog { - name String, + String name, } impl Speak for Dog { - fn String speak(*self) { + String speak(&self) { "woof".to_string() } } impl Greet for Dog { - fn String greet(*self) { + String greet(&self) { "hello".to_string() } } -pub fn void test_trait_impl() { +pub void test_trait_impl() { let d = Dog { name: "Rex".to_string() }; assert_eq!(d.speak(), "woof"); } -pub fn void test_trait_with_requirement() { +pub void test_trait_with_requirement() { let d = Dog { name: "Buddy".to_string() }; assert_eq!(d.speak(), "woof"); assert_eq!(d.greet(), "hello"); } -pub fn void run_tests() { +pub void run_tests() { test_trait_impl(); test_trait_with_requirement(); } diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 0025a0c..548fa97 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -1,4 +1,4 @@ -fn void main() { +void main() { println!("running common tests..."); common::test_package(); common::expr_test::run_tests(); diff --git a/src/analyzer.mist b/src/analyzer.mist index 8793f1a..59bd4e5 100644 --- a/src/analyzer.mist +++ b/src/analyzer.mist @@ -1,3 +1,3 @@ -fn void main() { +void main() { mist_analyzer::start(); } diff --git a/src/main.mist b/src/main.mist index 7a6b07e..ba7b066 100644 --- a/src/main.mist +++ b/src/main.mist @@ -4,8 +4,8 @@ use std::fs; use mist_api::builder; use mist_api::transpiler; -fn void main() { - let args Vec = env::args().collect(); +void main() { + Vec args = env::args().collect(); if args.len() < 2 { print_usage(); @@ -44,7 +44,7 @@ fn void main() { } } -fn void print_usage() { +void print_usage() { println!("Mist - the mist compiler\n"); println!("󰖟 View our documentation! \x1b[35mhttps://mist.selimaj.dev\x1b[0m"); println!(" Follow us on github! \x1b[35mhttps://github.com/mist-go\x1b[0m\n"); @@ -66,7 +66,7 @@ fn void print_usage() { println!(" \x1b[36m mist help\x1b[0m print this message\n"); } -fn void init_project(mut args Vec) { +void init_project(Vec mut args) { args.remove(0); process::Command::new("cargo") @@ -77,7 +77,7 @@ fn void init_project(mut args Vec) { .spawn() .expect("Failed to run cargo").wait().expect("Unable to wait"); - let is_lib bool = fs::metadata("src/lib.rs").is_ok(); + bool is_lib = fs::metadata("src/lib.rs").is_ok(); if is_lib { fs::remove_file("src/lib.rs").expect("Failed to remove src/lib.rs"); @@ -92,10 +92,10 @@ fn void init_project(mut args Vec) { println!("\n\x1b[34minfo\x1b[0m: Please open Cargo.toml and adjust `\x1b[35mname\x1b[0m = ` as needed, Thank you for using Mist!\n"); } -fn void inject_mist_target(is_lib bool) { - let toml_content String = fs::read_to_string("Cargo.toml").expect("Failed to read Cargo.toml"); +void inject_mist_target(bool is_lib) { + String toml_content = fs::read_to_string("Cargo.toml").expect("Failed to read Cargo.toml"); - let inject *str = if is_lib { + str& inject = if is_lib { "\n[lib]\nname = \"my_lib\"\npath = \".mist/src/lib.rs\"\n" } else { "\n[[bin]]\nname = \"my_bin\"\npath = \".mist/src/main.rs\"\n"