Merge pull request #42 from mist-go/init-and-expr-statements

Init and expression statements
This commit is contained in:
2026-05-21 11:16:48 +02:00
committed by GitHub
15 changed files with 193 additions and 320 deletions
+2
View File
@@ -27,3 +27,5 @@ target
/target
**/build
.mist/
+2 -2
View File
@@ -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"
+1 -1
View File
@@ -5,6 +5,6 @@ edition = "2024"
[[bin]]
name = "main"
path = "build/main.rs"
path = ".mist/src/main.rs"
[dependencies]
-4
View File
@@ -1,4 +0,0 @@
{
"src": "src",
"output": "build"
}
+3 -4
View File
@@ -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);
}
}
-3
View File
@@ -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();
}
+5 -25
View File
@@ -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<Statement>),
Fix {
initial: Box<Expression>,
prefixes: Vec<Prefix>,
@@ -37,7 +14,7 @@ pub enum Expression {
},
Binary {
lhs: Box<Expression>,
op: BinaryOp,
op: String,
rhs: Box<Expression>,
},
}
@@ -69,8 +46,11 @@ pub enum Postfix {
Call(Vec<Expression>),
MacroCall(String),
StructCall(Vec<(Identifier, Expression)>),
Assign(String, Box<Expression>),
Index(Expression),
As(TypeExpr),
Increment,
Decrement,
Try,
}
+4 -11
View File
@@ -3,19 +3,15 @@ use serde::Serialize;
use super::*;
#[derive(Debug, Clone, Serialize, Default)]
pub struct Block(pub Vec<Spanned<Statement>>);
pub struct Block(
pub Vec<Spanned<Expression>>,
pub Option<Spanned<Expression>>,
);
#[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<StatementBranch>,
@@ -39,9 +35,6 @@ pub enum Statement {
Return(Option<Expression>),
Break,
Continue,
Increment(Expression),
Decrement(Expression),
}
#[derive(Debug, Clone, Serialize)]
+74 -103
View File
@@ -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 = {
"+="
| "-="
| "/="
| "%="
| "&="
| "|="
| "^="
| "<<="
| ">>="
| "<<"
| ">>"
| "..="
| ".."
| "<="
| ">="
| "=="
| "!="
| "&&"
| "||"
| "+"
| "-"
| "*"
| "/"
| "%"
| "<"
| ">"
| "&"
| "|"
| "^"
| "="
}
// ------------------------------------------------------
+11 -44
View File
@@ -18,57 +18,18 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
Rule::expr => {
static PRATT_PARSER: OnceLock<PrattParser<Rule>> = 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<pest::iterators::Pair<'a, Rule>> 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<pest::iterators::Pair<'a, Rule>> for Postfix {
Rule::try_px => Ok(Postfix::Try),
Rule::increment => Ok(Postfix::Increment),
Rule::decrement => Ok(Postfix::Decrement),
_ => AstError::bug_unimplemented(pair),
}
}
+6 -29
View File
@@ -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<pest::iterators::Pair<'a, Rule>> for Block {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
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<pest::iterators::Pair<'a, Rule>> 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<pest::iterators::Pair<'a, Rule>> 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<pest::iterators::Pair<'a, Rule>> for Statement {
.collect::<AstResult<'a, Vec<_>>>(),
)),
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),
}
}
+2 -4
View File
@@ -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<String>, config: Config, root: PathBuf) -> bool {
pub fn build(mut args: Vec<String>, root: PathBuf) -> bool {
args.remove(0);
args.insert(1, "--message-format=json".to_string());
@@ -55,7 +53,7 @@ pub fn build(mut args: Vec<String>, 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);
+24 -52
View File
@@ -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<T: ToRust> ToRust for Spanned<T> {
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"),
}
}
}
+52 -2
View File
@@ -1,5 +1,6 @@
use <std::process>;
use <std::env>;
use <std::fs>;
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<String> 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");
}
+7 -36
View File
@@ -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<PathBuf> {
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")
}