Merge pull request #42 from mist-go/init-and-expr-statements
Init and expression statements
This commit is contained in:
@@ -27,3 +27,5 @@ target
|
|||||||
/target
|
/target
|
||||||
|
|
||||||
**/build
|
**/build
|
||||||
|
|
||||||
|
.mist/
|
||||||
|
|||||||
+2
-2
@@ -25,7 +25,7 @@ cargo_metadata = "0.23.1"
|
|||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mist"
|
name = "mist"
|
||||||
path = "build/main.rs"
|
path = ".mist/src/main.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mist-header"
|
name = "mist-header"
|
||||||
@@ -33,4 +33,4 @@ path = "src/_header.rs"
|
|||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "mist-analyzer"
|
name = "mist-analyzer"
|
||||||
path = "build/analyzer.rs"
|
path = ".mist/src/analyzer.rs"
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ edition = "2024"
|
|||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "main"
|
name = "main"
|
||||||
path = "build/main.rs"
|
path = ".mist/src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"src": "src",
|
|
||||||
"output": "build"
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,6 @@ pub class Application {
|
|||||||
|
|
||||||
pub constructor(str* name) {
|
pub constructor(str* name) {
|
||||||
self.name = name.to_string();
|
self.name = name.to_string();
|
||||||
|
|
||||||
self.tasks = new Vec();
|
self.tasks = new Vec();
|
||||||
self.plugins = new Vec();
|
self.plugins = new Vec();
|
||||||
|
|
||||||
@@ -79,15 +78,15 @@ pub class Application {
|
|||||||
self.logger.info("shutdown event");
|
self.logger.info("shutdown event");
|
||||||
}
|
}
|
||||||
|
|
||||||
event::Event::PluginLoaded(name) => {
|
event::Event::PluginLoaded[name] => {
|
||||||
println!("plugin loaded: {}", name);
|
println!("plugin loaded: {}", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
event::Event::TaskExecuted(name) => {
|
event::Event::TaskExecuted[name] => {
|
||||||
println!("task executed: {}", name);
|
println!("task executed: {}", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
event::Event::Error(message) => {
|
event::Event::Error[message] => {
|
||||||
self.logger.error(&message);
|
self.logger.error(&message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ pub mod event;
|
|||||||
void main() {
|
void main() {
|
||||||
var mut app_instance = new app::Application("mist-app");
|
var mut app_instance = new app::Application("mist-app");
|
||||||
|
|
||||||
// greeting::register(&mut app_instance);
|
|
||||||
// statistics::register(&mut app_instance);
|
|
||||||
|
|
||||||
app_instance.boot();
|
app_instance.boot();
|
||||||
app_instance.run();
|
app_instance.run();
|
||||||
}
|
}
|
||||||
+5
-25
@@ -2,34 +2,11 @@ use serde::Serialize;
|
|||||||
|
|
||||||
use super::*;
|
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)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
Path(ExprPath),
|
Path(ExprPath),
|
||||||
|
Statement(Box<Statement>),
|
||||||
Fix {
|
Fix {
|
||||||
initial: Box<Expression>,
|
initial: Box<Expression>,
|
||||||
prefixes: Vec<Prefix>,
|
prefixes: Vec<Prefix>,
|
||||||
@@ -37,7 +14,7 @@ pub enum Expression {
|
|||||||
},
|
},
|
||||||
Binary {
|
Binary {
|
||||||
lhs: Box<Expression>,
|
lhs: Box<Expression>,
|
||||||
op: BinaryOp,
|
op: String,
|
||||||
rhs: Box<Expression>,
|
rhs: Box<Expression>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -69,8 +46,11 @@ pub enum Postfix {
|
|||||||
Call(Vec<Expression>),
|
Call(Vec<Expression>),
|
||||||
MacroCall(String),
|
MacroCall(String),
|
||||||
StructCall(Vec<(Identifier, Expression)>),
|
StructCall(Vec<(Identifier, Expression)>),
|
||||||
|
Assign(String, Box<Expression>),
|
||||||
Index(Expression),
|
Index(Expression),
|
||||||
As(TypeExpr),
|
As(TypeExpr),
|
||||||
|
Increment,
|
||||||
|
Decrement,
|
||||||
Try,
|
Try,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,19 +3,15 @@ use serde::Serialize;
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Default)]
|
#[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)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Expression(Expression),
|
|
||||||
Block(Block),
|
Block(Block),
|
||||||
|
|
||||||
VarDecl(VarDeclStmt),
|
VarDecl(VarDeclStmt),
|
||||||
Assign {
|
|
||||||
target: Expression,
|
|
||||||
compound: String,
|
|
||||||
value: Expression,
|
|
||||||
},
|
|
||||||
If {
|
If {
|
||||||
initial: StatementBranch,
|
initial: StatementBranch,
|
||||||
else_if: Vec<StatementBranch>,
|
else_if: Vec<StatementBranch>,
|
||||||
@@ -39,9 +35,6 @@ pub enum Statement {
|
|||||||
Return(Option<Expression>),
|
Return(Option<Expression>),
|
||||||
Break,
|
Break,
|
||||||
Continue,
|
Continue,
|
||||||
|
|
||||||
Increment(Expression),
|
|
||||||
Decrement(Expression),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
|||||||
+74
-103
@@ -29,11 +29,10 @@ keyword = {
|
|||||||
| "true"
|
| "true"
|
||||||
| "false"
|
| "false"
|
||||||
| "dyn"
|
| "dyn"
|
||||||
| "self"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier = @{
|
identifier = @{
|
||||||
!keyword ~ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")*
|
!(keyword ~ !(ASCII_ALPHANUMERIC | "_")) ~ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")*
|
||||||
}
|
}
|
||||||
|
|
||||||
integer = @{ ASCII_DIGIT+ }
|
integer = @{ ASCII_DIGIT+ }
|
||||||
@@ -77,14 +76,6 @@ visibility = { "pub" ~ ("(" ~ static_path ~ ")")? }
|
|||||||
mutable = { "mut" }
|
mutable = { "mut" }
|
||||||
var = { "var" }
|
var = { "var" }
|
||||||
|
|
||||||
// ======================================================
|
|
||||||
// ERROR RECOVERY
|
|
||||||
// ======================================================
|
|
||||||
|
|
||||||
unexpected_statement = {
|
|
||||||
(!(semicolon | "}" | statement) ~ ANY)+
|
|
||||||
}
|
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
// GENERICS
|
// GENERICS
|
||||||
// ======================================================
|
// ======================================================
|
||||||
@@ -143,11 +134,11 @@ literal = {
|
|||||||
// ======================================================
|
// ======================================================
|
||||||
|
|
||||||
tuple_pattern = {
|
tuple_pattern = {
|
||||||
"(" ~ (identifier ~ ("," ~ identifier)*) ~ ")"
|
"[" ~ (identifier ~ ("," ~ identifier)*) ~ "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
named_tuple_pattern = {
|
named_tuple_pattern = {
|
||||||
static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")"
|
static_path ~ "[" ~ (identifier ~ ("," ~ identifier)*)? ~ "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
struct_pattern = {
|
struct_pattern = {
|
||||||
@@ -339,79 +330,58 @@ top_level = {
|
|||||||
// ======================================================
|
// ======================================================
|
||||||
|
|
||||||
block = {
|
block = {
|
||||||
"{" ~ (statement | unexpected_statement)* ~ "}"
|
"{" ~ statement_list ~ expr? ~ "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
statement_list = {
|
||||||
|
statement*
|
||||||
}
|
}
|
||||||
|
|
||||||
statement = _{
|
statement = _{
|
||||||
match_stmt
|
control_flow
|
||||||
| if_stmt
|
| (expr ~ semicolon)
|
||||||
| 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// BASIC STATEMENTS
|
// BASIC STATEMENTS
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
expr_stmt = {
|
basic_stmt = {
|
||||||
expr ~ semicolon
|
return_stmt
|
||||||
|
| break_stmt
|
||||||
|
| continue_stmt
|
||||||
|
| var_decl_statement
|
||||||
}
|
}
|
||||||
|
|
||||||
return_stmt = {
|
return_stmt = {
|
||||||
"return" ~ expr? ~ semicolon
|
"return" ~ expr?
|
||||||
}
|
}
|
||||||
|
|
||||||
break_stmt = {
|
break_stmt = {
|
||||||
"break" ~ semicolon
|
"break"
|
||||||
}
|
}
|
||||||
|
|
||||||
continue_stmt = {
|
continue_stmt = {
|
||||||
"continue" ~ semicolon
|
"continue"
|
||||||
}
|
}
|
||||||
|
|
||||||
var_decl_statement = {
|
var_decl_statement = {
|
||||||
var_decl ~ ("=" ~ expr)? ~ semicolon
|
var_decl ~ ("=" ~ expr)?
|
||||||
}
|
|
||||||
|
|
||||||
increment_statement = {
|
|
||||||
expr ~ "++" ~ semicolon
|
|
||||||
}
|
|
||||||
|
|
||||||
decrement_statement = {
|
|
||||||
expr ~ "--" ~ semicolon
|
|
||||||
}
|
|
||||||
|
|
||||||
compound_assign = {
|
|
||||||
"="
|
|
||||||
| "+="
|
|
||||||
| "-="
|
|
||||||
| "/="
|
|
||||||
| "%="
|
|
||||||
| "&="
|
|
||||||
| "|="
|
|
||||||
| "^="
|
|
||||||
| "<<="
|
|
||||||
| ">>="
|
|
||||||
}
|
|
||||||
|
|
||||||
assign_statement = {
|
|
||||||
expr ~ compound_assign ~ expr ~ semicolon
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// CONDITIONALS
|
// CONDITIONALS
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
|
control_flow = {
|
||||||
|
if_stmt
|
||||||
|
| while_stmt
|
||||||
|
| c_for_stmt
|
||||||
|
| for_stmt
|
||||||
|
| match_stmt
|
||||||
|
| block
|
||||||
|
}
|
||||||
|
|
||||||
statement_branch = { "(" ~ expr ~ ")" ~ statement }
|
statement_branch = { "(" ~ expr ~ ")" ~ statement }
|
||||||
|
|
||||||
else_if = {
|
else_if = {
|
||||||
@@ -478,7 +448,7 @@ array = {
|
|||||||
// MACROS
|
// MACROS
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
macro_inner_v = {
|
macro_inner_v = @{
|
||||||
string_lit
|
string_lit
|
||||||
| ("(" ~ macro_inner_v* ~ ")")
|
| ("(" ~ macro_inner_v* ~ ")")
|
||||||
| (!("(" | ")") ~ ANY)
|
| (!("(" | ")") ~ ANY)
|
||||||
@@ -497,7 +467,9 @@ expr_path = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
primary = {
|
primary = {
|
||||||
literal
|
control_flow
|
||||||
|
| basic_stmt
|
||||||
|
| literal
|
||||||
| expr_path
|
| expr_path
|
||||||
| tuple
|
| tuple
|
||||||
| array
|
| array
|
||||||
@@ -539,6 +511,14 @@ try_px = {
|
|||||||
"?"
|
"?"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
increment = {
|
||||||
|
"++"
|
||||||
|
}
|
||||||
|
|
||||||
|
decrement = {
|
||||||
|
"--"
|
||||||
|
}
|
||||||
|
|
||||||
postfix = {
|
postfix = {
|
||||||
field_px
|
field_px
|
||||||
| call_px
|
| call_px
|
||||||
@@ -547,6 +527,8 @@ postfix = {
|
|||||||
| index_px
|
| index_px
|
||||||
| as_px
|
| as_px
|
||||||
| try_px
|
| try_px
|
||||||
|
| increment
|
||||||
|
| decrement
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
@@ -570,51 +552,40 @@ prefix = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// OPERATORS (Arranged carefully for PEG priority matching)
|
// OPERATORS
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|
||||||
shl = { "<<" }
|
bin_op = {
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
|
|||||||
@@ -18,57 +18,18 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
|
|||||||
Rule::expr => {
|
Rule::expr => {
|
||||||
static PRATT_PARSER: OnceLock<PrattParser<Rule>> = OnceLock::new();
|
static PRATT_PARSER: OnceLock<PrattParser<Rule>> = OnceLock::new();
|
||||||
let pratt = PRATT_PARSER.get_or_init(|| {
|
let pratt = PRATT_PARSER.get_or_init(|| {
|
||||||
use Rule::*;
|
|
||||||
use pest::pratt_parser::{Assoc::*, Op};
|
use pest::pratt_parser::{Assoc::*, Op};
|
||||||
|
|
||||||
PrattParser::new()
|
PrattParser::new().op(Op::infix(Rule::bin_op, Left))
|
||||||
.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))
|
|
||||||
});
|
});
|
||||||
|
|
||||||
pratt
|
pratt
|
||||||
.map_primary(|primary_pair| Expression::try_from(primary_pair))
|
.map_primary(|primary_pair| Expression::try_from(primary_pair))
|
||||||
.map_infix(|lhs, op, rhs| {
|
.map_infix(|expr, 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),
|
|
||||||
};
|
|
||||||
|
|
||||||
ast_expr!(Expression::Binary {
|
ast_expr!(Expression::Binary {
|
||||||
lhs: lhs.map(Box::new),
|
lhs: expr.map(Box::new).get_map(Box::new),
|
||||||
op: Ok(bin_op) as AstResult<'_, BinaryOp>,
|
op: Ok(op.as_str().to_string()) as AstResult<'_, String>,
|
||||||
rhs: rhs.map(Box::new),
|
rhs: rhs.map(Box::new).get_map(Box::new),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.parse(inner)
|
.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::static_path => ast_expr!(Expression::Path(pair.try_into())),
|
||||||
Rule::literal => ast_expr!(Expression::Literal(pair.try_into())),
|
Rule::literal => ast_expr!(Expression::Literal(pair.try_into())),
|
||||||
Rule::expr_path => ast_expr!(Expression::Path(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),
|
_ => 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::try_px => Ok(Postfix::Try),
|
||||||
|
|
||||||
|
Rule::increment => Ok(Postfix::Increment),
|
||||||
|
Rule::decrement => Ok(Postfix::Decrement),
|
||||||
|
|
||||||
_ => AstError::bug_unimplemented(pair),
|
_ => AstError::bug_unimplemented(pair),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use crate::{
|
|||||||
Rule,
|
Rule,
|
||||||
ast::*,
|
ast::*,
|
||||||
ast_ensure, ast_expr,
|
ast_ensure, ast_expr,
|
||||||
error::{AstError, AstResult, ErrorCode, IntoErr, collect_recovered},
|
error::{AstError, AstResult, IntoErr, collect_recovered},
|
||||||
parser::listen_rule,
|
parser::listen_rule,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -10,8 +10,10 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Block {
|
|||||||
type Error = AstError<'a, Self>;
|
type Error = AstError<'a, Self>;
|
||||||
|
|
||||||
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
|
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_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();
|
let mut inner = pair.clone().into_inner();
|
||||||
|
|
||||||
match rule {
|
match rule {
|
||||||
Rule::statement => Statement::try_from(inner.next().unwrap()),
|
Rule::statement | Rule::basic_stmt | Rule::control_flow => {
|
||||||
|
Statement::try_from(inner.next().unwrap())
|
||||||
Rule::expr_stmt => {
|
|
||||||
ast_expr!(Statement::Expression(inner.next().unwrap().try_into()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule::block => ast_expr!(Statement::Block(pair.try_into())),
|
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),
|
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(
|
Rule::match_stmt => ast_expr!(Statement::Match(
|
||||||
inner.next().unwrap().try_into(),
|
inner.next().unwrap().try_into(),
|
||||||
inner
|
inner
|
||||||
@@ -107,23 +101,6 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Statement {
|
|||||||
.collect::<AstResult<'a, Vec<_>>>(),
|
.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),
|
_ => AstError::bug_unimplemented(pair),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -8,8 +8,6 @@ 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::{RustMap, find_mapping, get_mapping};
|
||||||
|
|
||||||
use crate::transpiler::Config;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MistDiagnosticMessage {
|
pub struct MistDiagnosticMessage {
|
||||||
pub message: String,
|
pub message: String,
|
||||||
@@ -26,7 +24,7 @@ pub enum MistDiagnostic {
|
|||||||
Rust(CompilerMessage),
|
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.remove(0);
|
||||||
args.insert(1, "--message-format=json".to_string());
|
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
|
let mist_file = span
|
||||||
.file_name
|
.file_name
|
||||||
.replacen(&config.output, &config.src, 1)
|
.replacen(".mist/src", "src", 1)
|
||||||
.replace(".rs", ".mist");
|
.replace(".rs", ".mist");
|
||||||
|
|
||||||
let mist_path = root.join(&mist_file);
|
let mist_path = root.join(&mist_file);
|
||||||
|
|||||||
+24
-52
@@ -1,8 +1,8 @@
|
|||||||
use mist_parser::ast::{
|
use mist_parser::ast::{
|
||||||
Attribute, BinaryOp, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression,
|
Attribute, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression, FieldDecl,
|
||||||
FieldDecl, FunctionDecl, Generic, GenericDecl, Generics, GenericsDecl, Identifier, ImplDecl,
|
FunctionDecl, Generic, GenericDecl, Generics, GenericsDecl, Identifier, ImplDecl, Literal,
|
||||||
Literal, Path, Pattern, Postfix, Prefix, Spanned, Statement, StatementBranch, TopLevel,
|
Path, Pattern, Postfix, Prefix, Spanned, Statement, StatementBranch, TopLevel, TopLevelKind,
|
||||||
TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarDecl, VarDeclStmt, Visibility,
|
TypeExpr, TypeExprKind, TypePostfix, VarDecl, VarDeclStmt, Visibility,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -169,6 +169,12 @@ impl GetRust for Expression {
|
|||||||
match self {
|
match self {
|
||||||
Expression::Path(path) => path.get_rust(),
|
Expression::Path(path) => path.get_rust(),
|
||||||
Expression::Literal(literal) => literal.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 {
|
Expression::Fix {
|
||||||
initial,
|
initial,
|
||||||
prefixes,
|
prefixes,
|
||||||
@@ -181,29 +187,7 @@ impl GetRust for Expression {
|
|||||||
}
|
}
|
||||||
// Safely integrated to handle the tree structure built by the Pratt Parser
|
// Safely integrated to handle the tree structure built by the Pratt Parser
|
||||||
Expression::Binary { lhs, op, rhs } => {
|
Expression::Binary { lhs, op, rhs } => {
|
||||||
let op_str = match op {
|
format!("{} {} {}", lhs.get_rust(), op, rhs.get_rust())
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,6 +297,10 @@ impl GetRust for Postfix {
|
|||||||
Postfix::As(ty) => format!(" as {}", ty.get_rust()),
|
Postfix::As(ty) => format!(" as {}", ty.get_rust()),
|
||||||
|
|
||||||
Postfix::Try => String::from("?"),
|
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 {
|
impl ToRust for Block {
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
fn to_rust(self, cg: &mut RustCodegen) {
|
||||||
for stmt in self.0 {
|
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 {
|
impl ToRust for Statement {
|
||||||
fn to_rust(self, cg: &mut RustCodegen) {
|
fn to_rust(self, cg: &mut RustCodegen) {
|
||||||
match self {
|
match self {
|
||||||
Statement::Expression(expr) => {
|
|
||||||
cg.add_indentedln(&format!("{};", expr.get_rust()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Statement::Block(block) => {
|
Statement::Block(block) => {
|
||||||
cg.add_indentedln("{");
|
cg.add_indentedln("{");
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
@@ -625,20 +613,7 @@ impl ToRust for Statement {
|
|||||||
.map(|e| format!(" = {}", e.get_rust()))
|
.map(|e| format!(" = {}", e.get_rust()))
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
cg.add_indentedln(&format!("let {}{};", decl.get_rust(), init));
|
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(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement::Match(expr, match_items) => {
|
Statement::Match(expr, match_items) => {
|
||||||
@@ -733,14 +708,11 @@ impl ToRust for Statement {
|
|||||||
|
|
||||||
Statement::Return(expr) => {
|
Statement::Return(expr) => {
|
||||||
let val = expr.map(|e| e.get_rust()).unwrap_or_default();
|
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::Break => cg.add_indentedln("break"),
|
||||||
Statement::Continue => cg.add_indentedln("continue;"),
|
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())),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-2
@@ -1,5 +1,6 @@
|
|||||||
use <std::process>;
|
use <std::process>;
|
||||||
use <std::env>;
|
use <std::env>;
|
||||||
|
use <std::fs>;
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod codegen;
|
pub mod codegen;
|
||||||
@@ -15,9 +16,12 @@ void main() {
|
|||||||
|
|
||||||
match (args[1].as_str()) {
|
match (args[1].as_str()) {
|
||||||
"run" | "build" | "check" | "r" | "b" | "c" => {
|
"run" | "build" | "check" | "r" | "b" | "c" => {
|
||||||
var (config, root) = transpiler::build();
|
|
||||||
|
var root = transpiler::build();
|
||||||
|
|
||||||
println!("");
|
println!("");
|
||||||
if (builder::build(args, config, root)) {
|
|
||||||
|
if (builder::build(args, root)) {
|
||||||
println!("\x1b[32m\nBuild successful\x1b[0m");
|
println!("\x1b[32m\nBuild successful\x1b[0m");
|
||||||
} else {
|
} else {
|
||||||
println!("\x1b[31m\nBuild failed\x1b[0m");
|
println!("\x1b[31m\nBuild failed\x1b[0m");
|
||||||
@@ -26,6 +30,9 @@ void main() {
|
|||||||
"transpile" | "t" => {
|
"transpile" | "t" => {
|
||||||
transpiler::build();
|
transpiler::build();
|
||||||
}
|
}
|
||||||
|
"init" => {
|
||||||
|
init_project(args);
|
||||||
|
}
|
||||||
"version" | "--version" | "-v" => {
|
"version" | "--version" | "-v" => {
|
||||||
println!("mist {}", env!("CARGO_PKG_VERSION"));
|
println!("mist {}", env!("CARGO_PKG_VERSION"));
|
||||||
}
|
}
|
||||||
@@ -55,6 +62,49 @@ void print_usage() {
|
|||||||
println!(
|
println!(
|
||||||
" \x1b[36m mist check\x1b[0m,\x1b[36m c\x1b[0m check the project in the current directory\n"
|
" \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 version \x1b[0m print the compiler version\n");
|
||||||
println!(" \x1b[36m mist help\x1b[0m print this message\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
@@ -6,25 +6,16 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use mist_parser::error::ParseError;
|
use mist_parser::error::ParseError;
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
pub fn build() -> PathBuf {
|
||||||
pub struct Config {
|
|
||||||
pub src: String,
|
|
||||||
pub output: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn build() -> (Config, PathBuf) {
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
let root = find_project_root().unwrap_or_else(|| {
|
let root = std::env::current_dir()
|
||||||
panic!("error: could not find project root (mist.json)");
|
.ok()
|
||||||
});
|
.expect("Unable to find project root");
|
||||||
|
|
||||||
let config = load_config(&root);
|
let src_dir = root.join("src");
|
||||||
|
let out_dir = root.join(".mist/src");
|
||||||
let src_dir = root.join(&config.src);
|
|
||||||
let out_dir = root.join(&config.output);
|
|
||||||
|
|
||||||
build_dir(&root, &src_dir, &src_dir, &out_dir);
|
build_dir(&root, &src_dir, &src_dir, &out_dir);
|
||||||
|
|
||||||
@@ -35,7 +26,7 @@ pub fn build() -> (Config, PathBuf) {
|
|||||||
elapsed
|
elapsed
|
||||||
);
|
);
|
||||||
|
|
||||||
(config, root)
|
root
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_dir(root: &Path, base_src: &Path, current_dir: &Path, out_dir: &Path) {
|
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
|
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")
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user