diff --git a/.gitignore b/.gitignore index e4cd9b8..6351270 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ target /target **/build + +.mist/ diff --git a/Cargo.toml b/Cargo.toml index 55367dc..e4e5dc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ cargo_metadata = "0.23.1" [[bin]] name = "mist" -path = "build/main.rs" +path = ".mist/src/main.rs" [[bin]] name = "mist-header" @@ -33,4 +33,4 @@ path = "src/_header.rs" [[bin]] name = "mist-analyzer" -path = "build/analyzer.rs" +path = ".mist/src/analyzer.rs" diff --git a/mist-test/Cargo.toml b/mist-test/Cargo.toml index a02d622..3973e4b 100644 --- a/mist-test/Cargo.toml +++ b/mist-test/Cargo.toml @@ -5,6 +5,6 @@ edition = "2024" [[bin]] name = "main" -path = "build/main.rs" +path = ".mist/src/main.rs" [dependencies] diff --git a/mist-test/mist.json b/mist-test/mist.json deleted file mode 100644 index 6632b01..0000000 --- a/mist-test/mist.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "src": "src", - "output": "build" -} \ No newline at end of file diff --git a/mist-test/src/app.mist b/mist-test/src/app.mist index 42072ac..5c09745 100644 --- a/mist-test/src/app.mist +++ b/mist-test/src/app.mist @@ -15,7 +15,6 @@ pub class Application { pub constructor(str* name) { self.name = name.to_string(); - self.tasks = new Vec(); self.plugins = new Vec(); @@ -79,15 +78,15 @@ pub class Application { self.logger.info("shutdown event"); } - event::Event::PluginLoaded(name) => { + event::Event::PluginLoaded[name] => { println!("plugin loaded: {}", name); } - event::Event::TaskExecuted(name) => { + event::Event::TaskExecuted[name] => { println!("task executed: {}", name); } - event::Event::Error(message) => { + event::Event::Error[message] => { self.logger.error(&message); } } diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 853e686..3729e97 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -7,9 +7,6 @@ pub mod event; void main() { var mut app_instance = new app::Application("mist-app"); - // greeting::register(&mut app_instance); - // statistics::register(&mut app_instance); - app_instance.boot(); app_instance.run(); } \ No newline at end of file diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index 257448d..77962cb 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -2,34 +2,11 @@ use serde::Serialize; use super::*; -#[derive(Debug, Clone, Serialize)] -pub enum BinaryOp { - Plus, - Minus, - Multiply, - Divide, - Modulo, - Equal, - NotEqual, - LessThan, - GreaterThan, - LessThanOrEqual, - GreaterThanOrEqual, - And, - Or, - ShiftLeft, - ShiftRight, - RangeInclusive, - RangeExclusive, - BitAnd, - BitOr, - BitXor, -} - #[derive(Debug, Clone, Serialize)] pub enum Expression { Literal(Literal), Path(ExprPath), + Statement(Box), Fix { initial: Box, prefixes: Vec, @@ -37,7 +14,7 @@ pub enum Expression { }, Binary { lhs: Box, - op: BinaryOp, + op: String, rhs: Box, }, } @@ -69,8 +46,11 @@ pub enum Postfix { Call(Vec), MacroCall(String), StructCall(Vec<(Identifier, Expression)>), + Assign(String, Box), Index(Expression), As(TypeExpr), + Increment, + Decrement, Try, } diff --git a/parser/src/ast/statement.rs b/parser/src/ast/statement.rs index 7ec8ccd..89a2d44 100644 --- a/parser/src/ast/statement.rs +++ b/parser/src/ast/statement.rs @@ -3,19 +3,15 @@ use serde::Serialize; use super::*; #[derive(Debug, Clone, Serialize, Default)] -pub struct Block(pub Vec>); +pub struct Block( + pub Vec>, + pub Option>, +); #[derive(Debug, Clone, Serialize)] pub enum Statement { - Expression(Expression), Block(Block), - VarDecl(VarDeclStmt), - Assign { - target: Expression, - compound: String, - value: Expression, - }, If { initial: StatementBranch, else_if: Vec, @@ -39,9 +35,6 @@ pub enum Statement { Return(Option), Break, Continue, - - Increment(Expression), - Decrement(Expression), } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 7e480d5..3b08ce8 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -29,11 +29,10 @@ keyword = { | "true" | "false" | "dyn" - | "self" } identifier = @{ - !keyword ~ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* + !(keyword ~ !(ASCII_ALPHANUMERIC | "_")) ~ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } integer = @{ ASCII_DIGIT+ } @@ -77,14 +76,6 @@ visibility = { "pub" ~ ("(" ~ static_path ~ ")")? } mutable = { "mut" } var = { "var" } -// ====================================================== -// ERROR RECOVERY -// ====================================================== - -unexpected_statement = { - (!(semicolon | "}" | statement) ~ ANY)+ -} - // ====================================================== // GENERICS // ====================================================== @@ -143,11 +134,11 @@ literal = { // ====================================================== tuple_pattern = { - "(" ~ (identifier ~ ("," ~ identifier)*) ~ ")" + "[" ~ (identifier ~ ("," ~ identifier)*) ~ "]" } named_tuple_pattern = { - static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" + static_path ~ "[" ~ (identifier ~ ("," ~ identifier)*)? ~ "]" } struct_pattern = { @@ -339,79 +330,58 @@ top_level = { // ====================================================== block = { - "{" ~ (statement | unexpected_statement)* ~ "}" + "{" ~ statement_list ~ expr? ~ "}" +} + +statement_list = { + statement* } statement = _{ - match_stmt - | if_stmt - | while_stmt - | c_for_stmt - | for_stmt - | return_stmt - | break_stmt - | continue_stmt - | block - | increment_statement - | decrement_statement - | var_decl_statement - | assign_statement - | expr_stmt + control_flow + | (expr ~ semicolon) } // ------------------------------------------------------ // BASIC STATEMENTS // ------------------------------------------------------ -expr_stmt = { - expr ~ semicolon +basic_stmt = { + return_stmt + | break_stmt + | continue_stmt + | var_decl_statement } return_stmt = { - "return" ~ expr? ~ semicolon + "return" ~ expr? } break_stmt = { - "break" ~ semicolon + "break" } continue_stmt = { - "continue" ~ semicolon + "continue" } var_decl_statement = { - var_decl ~ ("=" ~ expr)? ~ semicolon -} - -increment_statement = { - expr ~ "++" ~ semicolon -} - -decrement_statement = { - expr ~ "--" ~ semicolon -} - -compound_assign = { - "=" - | "+=" - | "-=" - | "/=" - | "%=" - | "&=" - | "|=" - | "^=" - | "<<=" - | ">>=" -} - -assign_statement = { - expr ~ compound_assign ~ expr ~ semicolon + var_decl ~ ("=" ~ expr)? } // ------------------------------------------------------ // CONDITIONALS // ------------------------------------------------------ +control_flow = { + if_stmt + | while_stmt + | c_for_stmt + | for_stmt + | match_stmt + | block +} + statement_branch = { "(" ~ expr ~ ")" ~ statement } else_if = { @@ -478,7 +448,7 @@ array = { // MACROS // ------------------------------------------------------ -macro_inner_v = { +macro_inner_v = @{ string_lit | ("(" ~ macro_inner_v* ~ ")") | (!("(" | ")") ~ ANY) @@ -497,7 +467,9 @@ expr_path = { } primary = { - literal + control_flow + | basic_stmt + | literal | expr_path | tuple | array @@ -539,6 +511,14 @@ try_px = { "?" } +increment = { + "++" +} + +decrement = { + "--" +} + postfix = { field_px | call_px @@ -547,6 +527,8 @@ postfix = { | index_px | as_px | try_px + | increment + | decrement } // ------------------------------------------------------ @@ -570,51 +552,40 @@ prefix = { } // ------------------------------------------------------ -// OPERATORS (Arranged carefully for PEG priority matching) +// OPERATORS // ------------------------------------------------------ -shl = { "<<" } -shr = { ">>" } -range_inc = { "..=" } -range_exc = { ".." } -lte = { "<=" } -gte = { ">=" } -eq = { "==" } -neq = { "!=" } -and = { "&&" } -or = { "||" } -add = { "+" } -sub = { "-" } -mul = { "*" } -div = { "/" } -rem = { "%" } -lt = { "<" } -gt = { ">" } -bitand = { "&" } -bitor = { "|" } -bitxor = { "^" } - -bin_op = _{ - shl - | shr - | range_inc - | range_exc - | lte - | gte - | eq - | neq - | and - | or - | lt - | gt - | add - | sub - | mul - | div - | rem - | bitand - | bitor - | bitxor +bin_op = { + "+=" + | "-=" + | "/=" + | "%=" + | "&=" + | "|=" + | "^=" + | "<<=" + | ">>=" + | "<<" + | ">>" + | "..=" + | ".." + | "<=" + | ">=" + | "==" + | "!=" + | "&&" + | "||" + | "+" + | "-" + | "*" + | "/" + | "%" + | "<" + | ">" + | "&" + | "|" + | "^" + | "=" } // ------------------------------------------------------ diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 312a406..de33878 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -18,57 +18,18 @@ impl<'a> TryFrom> for Expression { Rule::expr => { static PRATT_PARSER: OnceLock> = OnceLock::new(); let pratt = PRATT_PARSER.get_or_init(|| { - use Rule::*; use pest::pratt_parser::{Assoc::*, Op}; - PrattParser::new() - .op(Op::infix(range_inc, Left) | Op::infix(range_exc, Left)) - .op(Op::infix(or, Left)) - .op(Op::infix(and, Left)) - .op(Op::infix(bitor, Left)) - .op(Op::infix(bitxor, Left)) - .op(Op::infix(bitand, Left)) - .op(Op::infix(eq, Left) | Op::infix(neq, Left)) - .op(Op::infix(lt, Left) - | Op::infix(lte, Left) - | Op::infix(gt, Left) - | Op::infix(gte, Left)) - .op(Op::infix(shl, Left) | Op::infix(shr, Left)) - .op(Op::infix(add, Left) | Op::infix(sub, Left)) - .op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(rem, Left)) + PrattParser::new().op(Op::infix(Rule::bin_op, Left)) }); pratt .map_primary(|primary_pair| Expression::try_from(primary_pair)) - .map_infix(|lhs, op, rhs| { - let bin_op = match op.as_rule() { - Rule::shl => BinaryOp::ShiftLeft, - Rule::shr => BinaryOp::ShiftRight, - Rule::range_inc => BinaryOp::RangeInclusive, - Rule::range_exc => BinaryOp::RangeExclusive, - Rule::lte => BinaryOp::LessThanOrEqual, - Rule::gte => BinaryOp::GreaterThanOrEqual, - Rule::eq => BinaryOp::Equal, - Rule::neq => BinaryOp::NotEqual, - Rule::and => BinaryOp::And, - Rule::or => BinaryOp::Or, - Rule::add => BinaryOp::Plus, - Rule::sub => BinaryOp::Minus, - Rule::mul => BinaryOp::Multiply, - Rule::div => BinaryOp::Divide, - Rule::rem => BinaryOp::Modulo, - Rule::lt => BinaryOp::LessThan, - Rule::gt => BinaryOp::GreaterThan, - Rule::bitand => BinaryOp::BitAnd, - Rule::bitor => BinaryOp::BitOr, - Rule::bitxor => BinaryOp::BitXor, - _ => return AstError::bug_unimplemented(op), - }; - + .map_infix(|expr, op, rhs| { ast_expr!(Expression::Binary { - lhs: lhs.map(Box::new), - op: Ok(bin_op) as AstResult<'_, BinaryOp>, - rhs: rhs.map(Box::new), + lhs: expr.map(Box::new).get_map(Box::new), + op: Ok(op.as_str().to_string()) as AstResult<'_, String>, + rhs: rhs.map(Box::new).get_map(Box::new), }) }) .parse(inner) @@ -117,6 +78,9 @@ impl<'a> TryFrom> for Expression { Rule::static_path => ast_expr!(Expression::Path(pair.try_into())), Rule::literal => ast_expr!(Expression::Literal(pair.try_into())), Rule::expr_path => ast_expr!(Expression::Path(pair.try_into())), + Rule::statement | Rule::basic_stmt | Rule::control_flow => ast_expr!( + Expression::Statement(pair.try_into().get_map(Box::new).map(Box::new)) + ), _ => AstError::bug_unimplemented(pair), } @@ -185,6 +149,9 @@ impl<'a> TryFrom> for Postfix { Rule::try_px => Ok(Postfix::Try), + Rule::increment => Ok(Postfix::Increment), + Rule::decrement => Ok(Postfix::Decrement), + _ => AstError::bug_unimplemented(pair), } } diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index 3b3f7ad..516d32d 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -2,7 +2,7 @@ use crate::{ Rule, ast::*, ast_ensure, ast_expr, - error::{AstError, AstResult, ErrorCode, IntoErr, collect_recovered}, + error::{AstError, AstResult, IntoErr, collect_recovered}, parser::listen_rule, }; @@ -10,8 +10,10 @@ impl<'a> TryFrom> for Block { type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let mut inner = pair.clone().into_inner(); + ast_ensure!(pair, Rule::block => { - ast_expr!(Block(collect_recovered(pair.into_inner()))) + ast_expr!(Block(collect_recovered(inner.next().unwrap().into_inner()), inner.next().map(Spanned::try_from).transpose())) }) } } @@ -39,10 +41,8 @@ impl<'a> TryFrom> for Statement { let mut inner = pair.clone().into_inner(); match rule { - Rule::statement => Statement::try_from(inner.next().unwrap()), - - Rule::expr_stmt => { - ast_expr!(Statement::Expression(inner.next().unwrap().try_into())) + Rule::statement | Rule::basic_stmt | Rule::control_flow => { + Statement::try_from(inner.next().unwrap()) } Rule::block => ast_expr!(Statement::Block(pair.try_into())), @@ -88,12 +88,6 @@ impl<'a> TryFrom> for Statement { body: inner.next().unwrap().try_into().map(Box::new), }), - Rule::assign_statement => ast_expr!(Statement::Assign { - target: inner.next().unwrap().try_into(), - compound: Ok(inner.next().unwrap().as_str().trim().to_string()) - as AstResult<'_, String>, - value: inner.next().unwrap().try_into(), - }), Rule::match_stmt => ast_expr!(Statement::Match( inner.next().unwrap().try_into(), inner @@ -107,23 +101,6 @@ impl<'a> TryFrom> for Statement { .collect::>>(), )), - Rule::increment_statement => { - ast_expr!(Statement::Increment(inner.next().unwrap().try_into())) - } - - Rule::decrement_statement => { - ast_expr!(Statement::Decrement(inner.next().unwrap().try_into())) - } - - Rule::unexpected_statement => { - return Err(AstError { - span: pair.as_span(), - error_code: ErrorCode::InvalidStatement, - error_message: "Invalid Statement".to_string(), - recovered: None, - }); - } - _ => AstError::bug_unimplemented(pair), } } diff --git a/src/builder.rs b/src/builder.rs index a65983a..34afc8a 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -8,8 +8,6 @@ use std::{ use cargo_metadata::{CompilerMessage, Message}; use mist_parser::rev_mapper::{RustMap, find_mapping, get_mapping}; -use crate::transpiler::Config; - #[derive(Debug, Clone)] pub struct MistDiagnosticMessage { pub message: String, @@ -26,7 +24,7 @@ pub enum MistDiagnostic { Rust(CompilerMessage), } -pub fn build(mut args: Vec, config: Config, root: PathBuf) -> bool { +pub fn build(mut args: Vec, root: PathBuf) -> bool { args.remove(0); args.insert(1, "--message-format=json".to_string()); @@ -55,7 +53,7 @@ pub fn build(mut args: Vec, config: Config, root: PathBuf) -> bool { let mist_file = span .file_name - .replacen(&config.output, &config.src, 1) + .replacen(".mist/src", "src", 1) .replace(".rs", ".mist"); let mist_path = root.join(&mist_file); diff --git a/src/codegen.rs b/src/codegen.rs index f8524f1..cc22d83 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,8 +1,8 @@ use mist_parser::ast::{ - Attribute, BinaryOp, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression, - FieldDecl, FunctionDecl, Generic, GenericDecl, Generics, GenericsDecl, Identifier, ImplDecl, - Literal, Path, Pattern, Postfix, Prefix, Spanned, Statement, StatementBranch, TopLevel, - TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarDecl, VarDeclStmt, Visibility, + Attribute, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression, FieldDecl, + FunctionDecl, Generic, GenericDecl, Generics, GenericsDecl, Identifier, ImplDecl, Literal, + Path, Pattern, Postfix, Prefix, Spanned, Statement, StatementBranch, TopLevel, TopLevelKind, + TypeExpr, TypeExprKind, TypePostfix, VarDecl, VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- @@ -169,6 +169,12 @@ impl GetRust for Expression { match self { Expression::Path(path) => path.get_rust(), Expression::Literal(literal) => literal.get_rust(), + Expression::Statement(stmt) => { + let mut cg = RustCodegen::new(); + cg.indent += 1; + stmt.to_rust(&mut cg); + cg.output + } Expression::Fix { initial, prefixes, @@ -181,29 +187,7 @@ impl GetRust for Expression { } // Safely integrated to handle the tree structure built by the Pratt Parser Expression::Binary { lhs, op, rhs } => { - let op_str = match op { - BinaryOp::Plus => "+", - BinaryOp::Minus => "-", - BinaryOp::Multiply => "*", - BinaryOp::Divide => "/", - BinaryOp::Modulo => "%", - BinaryOp::Equal => "==", - BinaryOp::NotEqual => "!=", - BinaryOp::LessThan => "<", - BinaryOp::GreaterThan => ">", - BinaryOp::LessThanOrEqual => "<=", - BinaryOp::GreaterThanOrEqual => ">=", - BinaryOp::And => "&&", - BinaryOp::Or => "||", - BinaryOp::ShiftLeft => "<<", - BinaryOp::ShiftRight => ">>", - BinaryOp::RangeInclusive => "..=", - BinaryOp::RangeExclusive => "..", - BinaryOp::BitAnd => "&", - BinaryOp::BitOr => "|", - BinaryOp::BitXor => "^", - }; - format!("{} {} {}", lhs.get_rust(), op_str, rhs.get_rust()) + format!("{} {} {}", lhs.get_rust(), op, rhs.get_rust()) } } } @@ -313,6 +297,10 @@ impl GetRust for Postfix { Postfix::As(ty) => format!(" as {}", ty.get_rust()), Postfix::Try => String::from("?"), + + Postfix::Assign(cmp, expr) => format!("{cmp} {}", expr.get_rust()), + Postfix::Increment => "+=1".to_string(), + Postfix::Decrement => "-=1".to_string(), } } } @@ -336,7 +324,11 @@ impl ToRust for Spanned { impl ToRust for Block { fn to_rust(self, cg: &mut RustCodegen) { for stmt in self.0 { - stmt.to_rust(cg); + cg.add_indentedln(&(stmt.get_rust() + ";")); + } + + if let Some(soft_return) = self.1 { + cg.add_indentedln(&soft_return.get_rust()); } } } @@ -608,10 +600,6 @@ impl ToRust for TopLevelKind { impl ToRust for Statement { fn to_rust(self, cg: &mut RustCodegen) { match self { - Statement::Expression(expr) => { - cg.add_indentedln(&format!("{};", expr.get_rust())); - } - Statement::Block(block) => { cg.add_indentedln("{"); cg.indent += 1; @@ -625,20 +613,7 @@ impl ToRust for Statement { .map(|e| format!(" = {}", e.get_rust())) .unwrap_or_default(); - cg.add_indentedln(&format!("let {}{};", decl.get_rust(), init)); - } - - Statement::Assign { - target, - compound, - value, - } => { - cg.add_indentedln(&format!( - "{} {} {};", - target.get_rust(), - compound, - value.get_rust(), - )); + cg.add_indentedln(&format!("let {}{}", decl.get_rust(), init)); } Statement::Match(expr, match_items) => { @@ -733,14 +708,11 @@ impl ToRust for Statement { Statement::Return(expr) => { let val = expr.map(|e| e.get_rust()).unwrap_or_default(); - cg.add_indentedln(&format!("return {};", val)); + cg.add_indentedln(&format!("return {}", val)); } - Statement::Break => cg.add_indentedln("break;"), - Statement::Continue => cg.add_indentedln("continue;"), - - Statement::Increment(e) => cg.add_indentedln(&format!("{}+=1;", e.get_rust())), - Statement::Decrement(e) => cg.add_indentedln(&format!("{}-=1;", e.get_rust())), + Statement::Break => cg.add_indentedln("break"), + Statement::Continue => cg.add_indentedln("continue"), } } } diff --git a/src/main.mist b/src/main.mist index 8171d3b..a86389b 100644 --- a/src/main.mist +++ b/src/main.mist @@ -1,5 +1,6 @@ use ; use ; +use ; pub mod builder; pub mod codegen; @@ -15,9 +16,12 @@ void main() { match (args[1].as_str()) { "run" | "build" | "check" | "r" | "b" | "c" => { - var (config, root) = transpiler::build(); + + var root = transpiler::build(); + println!(""); - if (builder::build(args, config, root)) { + + if (builder::build(args, root)) { println!("\x1b[32m\nBuild successful\x1b[0m"); } else { println!("\x1b[31m\nBuild failed\x1b[0m"); @@ -26,6 +30,9 @@ void main() { "transpile" | "t" => { transpiler::build(); } + "init" => { + init_project(args); + } "version" | "--version" | "-v" => { println!("mist {}", env!("CARGO_PKG_VERSION")); } @@ -55,6 +62,49 @@ void print_usage() { println!( " \x1b[36m mist check\x1b[0m,\x1b[36m c\x1b[0m check the project in the current directory\n" ); + println!( + " \x1b[36m mist init\x1b[0m initialize a project in the current folder\n" + ); println!(" \x1b[36m mist version \x1b[0m print the compiler version\n"); println!(" \x1b[36m mist help\x1b[0m print this message\n"); } + +void init_project(Vec mut args) { + args.remove(0); + + new process::Command("cargo") + .args(args) + .stdout(process::Stdio::inherit()) + .stderr(process::Stdio::inherit()) + .stdin(process::Stdio::inherit()) + .spawn() + .expect("Failed to run cargo").wait().expect("Unable to wait"); + + 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"); + fs::write("src/lib.mist", "void test() {\n}").expect("Failed to create src/lib.mist"); + } else { + fs::remove_file("src/main.rs").expect("Failed to remove src/main.rs"); + fs::write("src/main.mist", "void main() {\n println!(\"Hello, World!\");\n}\n").expect("Failed to create src/main.mist"); + } + + inject_mist_target(is_lib); + + println!("\n\x1b[34minfo\x1b[0m: Please open Cargo.toml and adjust `\x1b[35mname\x1b[0m = ` as needed, Thank you for using Mist!\n"); +} + +void inject_mist_target(bool is_lib) { + String toml_content = fs::read_to_string("Cargo.toml").expect("Failed to read Cargo.toml"); + + str* inject; + + if (is_lib) { + inject = "\n[lib]\nname = \"my_lib\"\npath = \".mist/src/lib.rs\"\n"; + } else { + inject = "\n[[bin]]\nname = \"my_bin\"\npath = \".mist/src/main.rs\"\n"; + } + + fs::write("Cargo.toml", toml_content+inject).expect("Failed to create src/main.mist"); +} diff --git a/src/transpiler.rs b/src/transpiler.rs index ec282c2..349b7c4 100644 --- a/src/transpiler.rs +++ b/src/transpiler.rs @@ -6,25 +6,16 @@ use std::{ }; use mist_parser::error::ParseError; -use serde::Deserialize; -#[derive(Deserialize)] -pub struct Config { - pub src: String, - pub output: String, -} - -pub fn build() -> (Config, PathBuf) { +pub fn build() -> PathBuf { let start = Instant::now(); - let root = find_project_root().unwrap_or_else(|| { - panic!("error: could not find project root (mist.json)"); - }); + let root = std::env::current_dir() + .ok() + .expect("Unable to find project root"); - let config = load_config(&root); - - let src_dir = root.join(&config.src); - let out_dir = root.join(&config.output); + let src_dir = root.join("src"); + let out_dir = root.join(".mist/src"); build_dir(&root, &src_dir, &src_dir, &out_dir); @@ -35,7 +26,7 @@ pub fn build() -> (Config, PathBuf) { elapsed ); - (config, root) + root } fn build_dir(root: &Path, base_src: &Path, current_dir: &Path, out_dir: &Path) { @@ -173,23 +164,3 @@ fn should_skip(source: &Path, output: &Path) -> bool { } false } - -pub fn find_project_root() -> Option { - let mut dir = std::env::current_dir().ok()?; - - loop { - if dir.join("mist.json").exists() { - return Some(dir); - } - - if !dir.pop() { - return None; - } - } -} - -fn load_config(root: &Path) -> Config { - let content = fs::read_to_string(root.join("mist.json")).expect("failed to read mist.json"); - - serde_json::from_str(&content).expect("invalid mist.json format") -}