Merge pull request #31 from mist-go/assignments-expressions

Improved Assignments & expressions
This commit is contained in:
2026-05-17 06:03:11 +02:00
committed by GitHub
12 changed files with 687 additions and 406 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ pub class Application {
void tick(self mut*) { void tick(self mut*) {
self.logger.info("tick"); self.logger.info("tick");
self.ticks = self.ticks + 1; self.ticks++;
var task = task::create_task("background-job"); var task = task::create_task("background-job");
-280
View File
@@ -1,280 +0,0 @@
use serde::Serialize;
#[derive(Debug, Clone, Serialize)]
pub struct Identifier(pub String);
#[derive(Debug, Clone, Serialize, Default)]
pub struct ParamList(pub Vec<VarDecl>);
#[derive(Debug, Clone, Serialize, Default)]
pub struct Block(pub Vec<Statement>);
#[derive(Debug, Clone, Serialize)]
pub enum TypePostfix {
Ref,
RefMut,
RefLifetime(Identifier),
RefMutLifetime(Identifier),
}
#[derive(Debug, Clone, Serialize)]
pub enum Visibility {
Public,
PublicTarget(Path),
Private,
}
#[derive(Debug, Clone, Serialize)]
pub enum Attribute {
/// #[test]
Path(Path),
/// #[name = "value"]
NameValue { path: Path, value: Literal },
/// #[derive(Clone, Copy)]
List { path: Path, items: Vec<Attribute> },
}
#[derive(Debug, Clone, Serialize)]
pub enum TypeExprKind {
Path(Path),
PathParams(Path, Vec<TypeExpr>),
Tuple(Vec<TypeExpr>),
Lifetime(Identifier),
}
#[derive(Debug, Clone, Serialize)]
pub struct TypeExpr(pub TypeExprKind, pub Vec<TypePostfix>);
#[derive(Debug, Clone, Serialize)]
pub struct Path(pub Vec<Identifier>);
#[derive(Debug, Clone, Serialize)]
pub enum BinaryOp {
Plus,
Minus,
Multiply,
Divide,
Modulo,
Equal,
NotEqual,
LessThan,
GreaterThan,
LessThanOrEqual,
GreaterThanOrEqual,
And,
Or,
}
#[derive(Debug, Clone, Serialize)]
pub struct TopLevel(pub TopLevelKind, pub Vec<Attribute>);
#[derive(Debug, Clone, Serialize)]
pub enum TopLevelKind {
ModAttribute,
Import(Visibility, Path),
Mod(Visibility, Identifier),
ImplDecl(ImplDecl),
TraitDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
requirements: Vec<TypeExpr>,
items: Vec<FunctionDecl>,
},
EnumDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
fields: Vec<EnumItem>,
},
StructDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
fields: Vec<FieldDecl>,
},
FunctionDecl(FunctionDecl),
ClassDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
fields: Vec<FieldDeclStmt>,
constructor: ClassConstructor,
items: Vec<ClassItem>,
},
}
#[derive(Debug, Clone, Serialize)]
pub enum ClassItem {
Method(FunctionDecl),
ImplDecl(ImplDecl),
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct Generics(pub Vec<Generic>);
#[derive(Debug, Clone, Serialize)]
pub enum Generic {
Lifetime(Identifier),
Type(Identifier, Vec<TypeExpr>),
}
#[derive(Debug, Clone, Serialize)]
pub enum Pattern {
NamedTuple(Path, Vec<Identifier>),
Struct(Path, Vec<Identifier>),
Tuple(Vec<Identifier>),
Literal(Literal),
Path(Path),
Id(Identifier),
}
#[derive(Debug, Clone, Serialize)]
pub enum EnumItem {
Named(Identifier),
Tuple(Identifier, Vec<TypeExpr>),
Struct(Identifier, Vec<FieldDecl>),
}
#[derive(Debug, Clone, Serialize)]
pub struct ClassConstructor {
pub visibility: Visibility,
pub generics: Generics,
pub params: ParamList,
pub body: Block,
}
#[derive(Debug, Clone, Serialize)]
pub struct FunctionDecl {
pub visibility: Visibility,
pub name: Identifier,
pub generics: Generics,
pub params: ParamList,
pub return_type: TypeExpr,
pub body: Option<Block>,
}
#[derive(Debug, Clone, Serialize)]
pub enum Postfix {
FieldAccess(Identifier),
Call(Vec<Expression>),
MacroCall(String),
StructCall(Vec<(Identifier, Expression)>),
Index(Expression),
Binary(BinaryOp, Expression),
}
#[derive(Debug, Clone, Serialize)]
pub enum Prefix {
Ref,
RefMut,
Deref,
New,
Not,
}
#[derive(Debug, Clone, Serialize)]
pub enum Statement {
Expression(Expression),
Block(Block),
VarDecl(VarDeclStmt),
VarAssign(VarAssignStmt),
If {
initial: StatementBranch,
else_if: Vec<StatementBranch>,
else_branch: Option<Box<Statement>>,
},
While(StatementBranch),
CStyleFor {
init: Box<Statement>,
condition: Expression,
update: Box<Statement>,
body: Box<Statement>,
},
For {
mutable: bool,
pattern: Pattern,
iterator: Expression,
body: Box<Statement>,
},
Match(Expression, Vec<(Pattern, Block)>),
Return(Option<Expression>),
Break,
Continue,
}
#[derive(Debug, Clone, Serialize)]
pub struct ImplDecl {
pub generics: Generics,
pub target: TypeExpr,
pub trait_: Option<TypeExpr>,
pub methods: Vec<FunctionDecl>,
}
#[derive(Debug, Clone, Serialize)]
pub struct VarDecl {
pub mutable: bool,
pub name: Pattern,
pub type_: Option<TypeExpr>,
}
#[derive(Debug, Clone, Serialize)]
pub struct VarDeclStmt {
pub decl: VarDecl,
pub init: Option<Expression>,
}
#[derive(Debug, Clone, Serialize)]
pub struct FieldDecl {
pub visibility: Visibility,
pub type_: TypeExpr,
pub name: Identifier,
}
#[derive(Debug, Clone, Serialize)]
pub struct FieldDeclStmt {
pub decl: FieldDecl,
pub init: Option<Expression>,
}
#[derive(Debug, Clone, Serialize)]
pub struct VarAssignStmt {
pub target: Expression,
pub value: Expression,
}
#[derive(Debug, Clone, Serialize)]
pub struct StatementBranch {
pub condition: Expression,
pub body: Box<Statement>,
}
#[derive(Debug, Clone, Serialize)]
pub enum Expression {
Literal(Literal),
Path(Path),
Fix {
initial: Box<Expression>,
prefixes: Vec<Prefix>,
postfixes: Vec<Postfix>,
},
}
#[derive(Debug, Clone, Serialize)]
pub enum Literal {
String(String),
Int(i64),
Float(f64),
Bool(bool),
Tuple(Vec<Expression>),
}
impl TypeExpr {
pub fn no_px(kind: TypeExprKind) -> Self {
Self(kind, Vec::new())
}
}
+93
View File
@@ -0,0 +1,93 @@
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),
Fix {
initial: Box<Expression>,
prefixes: Vec<Prefix>,
postfixes: Vec<Postfix>,
},
Binary {
lhs: Box<Expression>,
op: BinaryOp,
rhs: Box<Expression>,
},
}
#[derive(Debug, Clone, Serialize)]
pub enum Literal {
String(String),
Int(i64),
Float(f64),
Bool(bool),
Tuple(Vec<Expression>),
Array(Vec<Expression>),
ArrayRepeat(Box<Expression>, Box<Expression>),
}
#[derive(Debug, Clone, Serialize)]
pub enum Pattern {
NamedTuple(Path, Vec<Identifier>),
Struct(Path, Vec<Identifier>),
Tuple(Vec<Identifier>),
Literal(Literal),
Path(Path),
Id(Identifier),
}
#[derive(Debug, Clone, Serialize)]
pub enum Postfix {
FieldAccess(Identifier, Option<Generics>),
Call(Vec<Expression>),
MacroCall(String),
StructCall(Vec<(Identifier, Expression)>),
Index(Expression),
As(TypeExpr),
}
#[derive(Debug, Clone, Serialize)]
pub enum Prefix {
Ref,
RefMut,
Deref,
New(Option<Generics>),
Not,
Neg,
}
#[derive(Debug, Clone, Serialize)]
pub struct ExprPathSegment {
pub ident: Identifier,
pub generics: Option<Generics>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ExprPath(pub Vec<ExprPathSegment>);
+43
View File
@@ -0,0 +1,43 @@
use serde::Serialize;
pub mod expr;
pub mod statement;
pub mod top_level;
pub use expr::*;
pub use statement::*;
pub use top_level::*;
#[derive(Debug, Clone, Serialize)]
pub struct Path(pub Vec<Identifier>);
#[derive(Debug, Clone, Serialize)]
pub struct Identifier(pub String);
#[derive(Debug, Clone, Serialize, Default)]
pub struct ParamList(pub Vec<VarDecl>);
#[derive(Debug, Clone, Serialize)]
pub enum TypePostfix {
Ref,
RefMut,
RefLifetime(Identifier),
RefMutLifetime(Identifier),
}
#[derive(Debug, Clone, Serialize)]
pub enum TypeExprKind {
Path(Path),
PathParams(Path, Vec<TypeExpr>),
Tuple(Vec<TypeExpr>),
Lifetime(Identifier),
}
#[derive(Debug, Clone, Serialize)]
pub struct TypeExpr(pub TypeExprKind, pub Vec<TypePostfix>);
impl TypeExpr {
pub fn no_px(kind: TypeExprKind) -> Self {
Self(kind, Vec::new())
}
}
+64
View File
@@ -0,0 +1,64 @@
use serde::Serialize;
use super::*;
#[derive(Debug, Clone, Serialize, Default)]
pub struct Block(pub Vec<Statement>);
#[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>,
else_branch: Option<Box<Statement>>,
},
While(StatementBranch),
CStyleFor {
init: Box<Statement>,
condition: Expression,
update: Box<Statement>,
body: Box<Statement>,
},
For {
mutable: bool,
pattern: Pattern,
iterator: Expression,
body: Box<Statement>,
},
Match(Expression, Vec<(Pattern, Block)>),
Return(Option<Expression>),
Break,
Continue,
Increment(Expression),
Decrement(Expression),
}
#[derive(Debug, Clone, Serialize)]
pub struct VarDecl {
pub mutable: bool,
pub name: Pattern,
pub type_: Option<TypeExpr>,
}
#[derive(Debug, Clone, Serialize)]
pub struct VarDeclStmt {
pub decl: VarDecl,
pub init: Option<Expression>,
}
#[derive(Debug, Clone, Serialize)]
pub struct StatementBranch {
pub condition: Expression,
pub body: Box<Statement>,
}
+121
View File
@@ -0,0 +1,121 @@
use serde::Serialize;
use super::*;
#[derive(Debug, Clone, Serialize)]
pub enum Visibility {
Public,
PublicTarget(Path),
Private,
}
#[derive(Debug, Clone, Serialize)]
pub enum Attribute {
/// #[test]
Path(Path),
/// #[name = "value"]
NameValue { path: Path, value: Literal },
/// #[derive(Clone, Copy)]
List { path: Path, items: Vec<Attribute> },
}
#[derive(Debug, Clone, Serialize)]
pub struct TopLevel(pub TopLevelKind, pub Vec<Attribute>);
#[derive(Debug, Clone, Serialize)]
pub enum TopLevelKind {
ModAttribute,
Import(Visibility, Path),
Mod(Visibility, Identifier),
ImplDecl(ImplDecl),
TraitDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
requirements: Vec<TypeExpr>,
items: Vec<FunctionDecl>,
},
EnumDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
fields: Vec<EnumItem>,
},
StructDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
fields: Vec<FieldDecl>,
},
FunctionDecl(FunctionDecl),
ClassDecl {
visibility: Visibility,
name: Identifier,
generics: Generics,
fields: Vec<FieldDeclStmt>,
constructor: ClassConstructor,
items: Vec<ClassItem>,
},
}
#[derive(Debug, Clone, Serialize)]
pub enum ClassItem {
Method(FunctionDecl),
ImplDecl(ImplDecl),
}
#[derive(Debug, Clone, Serialize, Default)]
pub struct Generics(pub Vec<Generic>);
#[derive(Debug, Clone, Serialize)]
pub enum Generic {
Lifetime(Identifier),
Type(Identifier, Vec<TypeExpr>),
}
#[derive(Debug, Clone, Serialize)]
pub enum EnumItem {
Named(Identifier),
Tuple(Identifier, Vec<TypeExpr>),
Struct(Identifier, Vec<FieldDecl>),
}
#[derive(Debug, Clone, Serialize)]
pub struct ClassConstructor {
pub visibility: Visibility,
pub generics: Generics,
pub params: ParamList,
pub body: Block,
}
#[derive(Debug, Clone, Serialize)]
pub struct FunctionDecl {
pub visibility: Visibility,
pub name: Identifier,
pub generics: Generics,
pub params: ParamList,
pub return_type: TypeExpr,
pub body: Option<Block>,
}
#[derive(Debug, Clone, Serialize)]
pub struct ImplDecl {
pub generics: Generics,
pub target: TypeExpr,
pub trait_: Option<TypeExpr>,
pub methods: Vec<FunctionDecl>,
}
#[derive(Debug, Clone, Serialize)]
pub struct FieldDecl {
pub visibility: Visibility,
pub type_: TypeExpr,
pub name: Identifier,
}
#[derive(Debug, Clone, Serialize)]
pub struct FieldDeclStmt {
pub decl: FieldDecl,
pub init: Option<Expression>,
}
+9 -1
View File
@@ -48,11 +48,19 @@ impl<'a, F> AstError<'a, F> {
} }
} }
#[track_caller]
pub fn bug_unimplemented<T>(pair: Pair<'a, Rule>) -> AstResult<'a, T, F> { pub fn bug_unimplemented<T>(pair: Pair<'a, Rule>) -> AstResult<'a, T, F> {
let loc = std::panic::Location::caller();
Err(Self { Err(Self {
span: pair.as_span(), span: pair.as_span(),
error_code: ErrorCode::AstGenBug, error_code: ErrorCode::AstGenBug,
error_message: format!("Possible bug, unimplemented: {:#?}", pair.as_rule()), error_message: format!(
"Possible bug, unimplemented: {:#?}, at {}:{}",
pair.as_rule(),
loc.file(),
loc.line(),
),
recovered: None, recovered: None,
}) })
} }
+98 -48
View File
@@ -323,6 +323,8 @@ statement = _{
| continue_stmt | continue_stmt
| block | block
| var_decl_statement | var_decl_statement
| increment_statement
| decrement_statement
} }
// ------------------------------------------------------ // ------------------------------------------------------
@@ -349,8 +351,29 @@ var_decl_statement = {
var_decl ~ ("=" ~ expr)? ~ semicolon var_decl ~ ("=" ~ expr)? ~ semicolon
} }
increment_statement = {
expr ~ "++" ~ semicolon
}
decrement_statement = {
expr ~ "--" ~ semicolon
}
compound_assign = {
"="
| "+="
| "-="
| "/="
| "%="
| "&="
| "|="
| "^="
| "<<="
| ">>="
}
assign_statement = { assign_statement = {
expr ~ "=" ~ expr ~ semicolon expr ~ compound_assign ~ expr ~ semicolon
} }
// ------------------------------------------------------ // ------------------------------------------------------
@@ -404,13 +427,19 @@ match_stmt = {
// ====================================================== // ======================================================
// ------------------------------------------------------ // ------------------------------------------------------
// TUPLES // TUPLES & ARRAYS
// ------------------------------------------------------ // ------------------------------------------------------
tuple = { tuple = {
"(" ~ (expr ~ ("," ~ expr)*)? ~ ")" "(" ~ (expr ~ ("," ~ expr)*)? ~ ")"
} }
array = {
"[" ~ expr ~ ";" ~ expr ~ "]" // Repeat notation: [0; 10]
| "[" ~ (expr ~ ("," ~ expr)* ~ ","?)? ~ "]" // Standard elements initialization
}
// ------------------------------------------------------ // ------------------------------------------------------
// MACROS // MACROS
// ------------------------------------------------------ // ------------------------------------------------------
@@ -424,10 +453,19 @@ macro_inner_v = {
// PRIMARY EXPRESSIONS // PRIMARY EXPRESSIONS
// ------------------------------------------------------ // ------------------------------------------------------
expr_path_segment = {
identifier ~ ("::" ~ generics)?
}
expr_path = {
expr_path_segment ~ ("::" ~ expr_path_segment)*
}
primary = { primary = {
literal literal
| static_path | expr_path
| tuple | tuple
| array
} }
// ------------------------------------------------------ // ------------------------------------------------------
@@ -435,7 +473,7 @@ primary = {
// ------------------------------------------------------ // ------------------------------------------------------
field_px = { field_px = {
"." ~ identifier "." ~ identifier ~ ("::" ~ generics)?
} }
call_px = { call_px = {
@@ -458,8 +496,8 @@ index_px = {
"[" ~ expr ~ "]" "[" ~ expr ~ "]"
} }
binary_px = { as_px = {
bin_op ~ expr "as" ~ type_expr
} }
postfix = { postfix = {
@@ -468,32 +506,19 @@ postfix = {
| macro_call_px | macro_call_px
| struct_px | struct_px
| index_px | index_px
| binary_px | as_px
} }
// ------------------------------------------------------ // ------------------------------------------------------
// PREFIX EXPRESSIONS // PREFIX EXPRESSIONS
// ------------------------------------------------------ // ------------------------------------------------------
deref_px = { deref_px = { "*" }
"*" mut_ref_px = { "&" ~ mutable }
} ref_px = { "&" }
new_px = { "new" ~ generics? }
mut_ref_px = { not_px = { "!" }
"&" ~ mutable neg_px = { "-" }
}
ref_px = {
"&"
}
new_px = {
"new"
}
not_px = {
"!"
}
prefix = { prefix = {
deref_px deref_px
@@ -501,36 +526,61 @@ prefix = {
| ref_px | ref_px
| new_px | new_px
| not_px | not_px
} | neg_px
prefix_list = {
prefix*
} }
// ------------------------------------------------------ // ------------------------------------------------------
// OPERATORS // OPERATORS (Arranged carefully for PEG priority matching)
// ------------------------------------------------------ // ------------------------------------------------------
bin_op = { 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
} }
// ------------------------------------------------------ // ------------------------------------------------------
// EXPRESSIONS // EXPRESSIONS
// ------------------------------------------------------ // ------------------------------------------------------
expr = { expr = { term ~ (bin_op ~ term)* }
prefix_list ~ primary ~ postfix*
} term = { prefix* ~ primary ~ postfix* }
+11 -1
View File
@@ -41,7 +41,7 @@ macro_rules! ast_ensure {
Err(AstError { Err(AstError {
span: $pair.as_span(), span: $pair.as_span(),
error_code: crate::error::ErrorCode::AstGenBug, error_code: crate::error::ErrorCode::AstGenBug,
error_message: format!("Possible bug: expected {:?}, got {}", $rule, $pair), error_message: format!("Possible bug: expected {:?}, got {:?}", $rule, $pair.as_rule()),
recovered: None, recovered: None,
}) })
} }
@@ -50,6 +50,16 @@ macro_rules! ast_ensure {
#[macro_export] #[macro_export]
macro_rules! ast_expr { macro_rules! ast_expr {
(use $r:expr, $($v:expr),* $(,)?) => {{
let mut analyzer = $crate::error::AstErrorAnalyzer(None);
$(
analyzer.get($v).get()?;
)*
analyzer.build($r)
}};
($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{ ($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{
let mut analyzer = $crate::error::AstErrorAnalyzer(None); let mut analyzer = $crate::error::AstErrorAnalyzer(None);
+134 -37
View File
@@ -1,40 +1,122 @@
use crate::{ use crate::{
Rule, Rule,
ast::*, ast::*,
ast_expr, ast_ensure, ast_expr,
error::{AstError, GetLength, IntoErr, collect_recovered, collect_recovered_map}, error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map},
}; };
use pest::pratt_parser::PrattParser;
use std::sync::OnceLock;
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression { impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Expression {
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 rule = pair.as_rule(); let rule = pair.as_rule();
let mut inner = pair.clone().into_inner(); let inner = pair.clone().into_inner();
match rule { match rule {
Rule::expr => { Rule::expr => {
let prefixes = inner static PRATT_PARSER: OnceLock<PrattParser<Rule>> = OnceLock::new();
.next() let pratt = PRATT_PARSER.get_or_init(|| {
.map(|p| collect_recovered::<Prefix, Prefix>(p.into_inner())) use Rule::*;
.unwrap_or_else(|| Ok(Vec::new())); use pest::pratt_parser::{Assoc::*, Op};
let exp = Expression::try_from(inner.next().unwrap()); 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))
});
if inner.len() > 0 || prefixes.len() > 0 { 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),
};
ast_expr!(Expression::Binary {
lhs: lhs.map(Box::new),
op: Ok(bin_op) as AstResult<'_, BinaryOp>,
rhs: rhs.map(Box::new),
})
})
.parse(inner)
}
Rule::term => {
let mut prefix_pairs = Vec::new();
let mut primary_pair = None;
let mut postfix_pairs = Vec::new();
for p in inner {
match p.as_rule() {
Rule::prefix => prefix_pairs.push(p),
Rule::primary => primary_pair = Some(p),
Rule::postfix => postfix_pairs.push(p),
_ => {}
}
}
let prefixes = collect_recovered::<Prefix, Prefix>(prefix_pairs.into_iter());
let exp = Expression::try_from(
primary_pair.expect("Term must contain a primary expression"),
);
let postfixes = collect_recovered::<Postfix, Postfix>(postfix_pairs.into_iter());
if postfixes.len() > 0 || prefixes.len() > 0 {
ast_expr!(Expression::Fix { ast_expr!(Expression::Fix {
initial: exp.map(Box::new), initial: exp.map(Box::new),
prefixes: prefixes, prefixes: prefixes,
postfixes: collect_recovered(inner), postfixes: postfixes,
}) })
} else { } else {
exp ast_expr!(use exp?, prefixes, postfixes)
} }
} }
Rule::primary => inner.next().unwrap().try_into(), Rule::tuple => {
ast_expr!(Expression::Literal(
collect_recovered(pair.into_inner())
.map(Literal::Tuple)
.get_map(Literal::Tuple)
))
}
Rule::primary => pair.into_inner().next().unwrap().try_into(),
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())),
_ => AstError::bug_unimplemented(pair), _ => AstError::bug_unimplemented(pair),
} }
@@ -50,8 +132,14 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Prefix {
Rule::deref_px => Self::Deref, Rule::deref_px => Self::Deref,
Rule::mut_ref_px => Self::RefMut, Rule::mut_ref_px => Self::RefMut,
Rule::ref_px => Self::Ref, Rule::ref_px => Self::Ref,
Rule::new_px => Self::New, Rule::new_px => Self::New(
pair.into_inner()
.next()
.map(|v| v.try_into().get())
.transpose()?,
),
Rule::not_px => Self::Not, Rule::not_px => Self::Not,
Rule::neg_px => Self::Neg,
_ => return AstError::bug_unimplemented(pair), _ => return AstError::bug_unimplemented(pair),
}) })
@@ -69,7 +157,10 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Postfix {
Rule::postfix => Postfix::try_from(inner.next().unwrap()), Rule::postfix => Postfix::try_from(inner.next().unwrap()),
Rule::field_px => { Rule::field_px => {
ast_expr!(Postfix::FieldAccess(inner.next().unwrap().try_into())) ast_expr!(Postfix::FieldAccess(
inner.next().unwrap().try_into(),
inner.next().map(Generics::try_from).transpose()
))
} }
Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))), Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))),
@@ -86,32 +177,38 @@ impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for Postfix {
ast_expr!(Postfix::Index(Expression::try_from(inner.next().unwrap()))) ast_expr!(Postfix::Index(Expression::try_from(inner.next().unwrap())))
} }
Rule::binary_px => {
let op_pair = inner.next().unwrap();
let op = match op_pair.as_str() {
"+" => 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,
_ => return AstError::bug_unimplemented(op_pair),
};
Ok(Postfix::Binary(op, inner.next().unwrap().try_into().get()?))
}
Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())), Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())),
Rule::as_px => {
ast_expr!(Postfix::As(inner.next().unwrap().try_into()))
}
_ => AstError::bug_unimplemented(pair), _ => AstError::bug_unimplemented(pair),
} }
} }
} }
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for ExprPath {
type Error = AstError<'a, Self>;
fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result<Self, Self::Error> {
ast_ensure!(pair, Rule::expr_path => {
ast_expr!(ExprPath(collect_recovered(pair.into_inner())))
})
}
}
impl<'a> TryFrom<pest::iterators::Pair<'a, Rule>> for ExprPathSegment {
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::expr_path_segment => {
ast_expr!(ExprPathSegment {
ident: Identifier::try_from(inner.next().unwrap()),
generics: inner.next().map(Generics::try_from).transpose(),
})
})
}
}
+12 -5
View File
@@ -88,13 +88,12 @@ 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!(VarAssignStmt { Rule::assign_statement => ast_expr!(Statement::Assign {
target: inner.next().unwrap().try_into(), 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(), value: inner.next().unwrap().try_into(),
}) }),
.map(Statement::VarAssign)
.get_map(Statement::VarAssign),
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
@@ -108,6 +107,14 @@ 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 => { Rule::unexpected_statement => {
return Err(AstError { return Err(AstError {
span: pair.as_span(), span: pair.as_span(),
+101 -33
View File
@@ -1,8 +1,8 @@
use mist_parser::ast::{ use mist_parser::ast::{
Attribute, BinaryOp, Block, ClassItem, EnumItem, Expression, FieldDecl, FunctionDecl, Generic, Attribute, BinaryOp, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression,
Generics, Identifier, ImplDecl, Literal, Path, Pattern, Postfix, Prefix, Statement, FieldDecl, FunctionDecl, Generic, Generics, Identifier, ImplDecl, Literal, Path, Pattern,
StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind,
VarDecl, VarDeclStmt, Visibility, TypePostfix, VarDecl, VarDeclStmt, Visibility,
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -137,6 +137,17 @@ impl GetRust for Literal {
.join(", ") .join(", ")
) )
} }
Self::Array(values) => format!(
"[{}]",
values
.iter()
.map(Expression::get_rust)
.collect::<Vec<_>>()
.join(", ")
),
Self::ArrayRepeat(value, repeat) => {
format!("[{}; {}]", value.get_rust(), repeat.get_rust())
}
} }
} }
} }
@@ -156,6 +167,32 @@ impl GetRust for Expression {
+ &Some(prefixes).get_rust() + &Some(prefixes).get_rust()
+ &postfixes.get_rust() + &postfixes.get_rust()
} }
// 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())
}
} }
} }
} }
@@ -167,7 +204,8 @@ impl GetRust for Prefix {
Self::Ref => "&", Self::Ref => "&",
Self::RefMut => "&mut ", Self::RefMut => "&mut ",
Self::Not => "!", Self::Not => "!",
Self::New => "", Self::New(_) => "",
Self::Neg => "-",
} }
.to_string() .to_string()
} }
@@ -179,6 +217,29 @@ impl GetRust for [Prefix] {
} }
} }
impl GetRust for ExprPath {
fn get_rust(&self) -> String {
self.0
.iter()
.map(ExprPathSegment::get_rust)
.collect::<Vec<_>>()
.join("::")
}
}
impl GetRust for ExprPathSegment {
fn get_rust(&self) -> String {
format!(
"{}{}",
self.ident.get_rust(),
self.generics
.as_ref()
.map(|v| format!("::{}", v.get_rust()))
.unwrap_or_default()
)
}
}
impl GetRust for Option<&Vec<Prefix>> { impl GetRust for Option<&Vec<Prefix>> {
fn get_rust(&self) -> String { fn get_rust(&self) -> String {
self.map(|prefixes| { self.map(|prefixes| {
@@ -186,8 +247,14 @@ impl GetRust for Option<&Vec<Prefix>> {
.iter() .iter()
.last() .last()
.map(|p| match p { .map(|p| match p {
Prefix::New => "::new", Prefix::New(generics) => format!(
_ => "", "::new{}",
generics
.as_ref()
.map(|v| format!("::{}", v.get_rust()))
.unwrap_or_default(),
),
_ => String::new(),
}) })
.unwrap_or_default() .unwrap_or_default()
.to_string() .to_string()
@@ -199,7 +266,14 @@ impl GetRust for Option<&Vec<Prefix>> {
impl GetRust for Postfix { impl GetRust for Postfix {
fn get_rust(&self) -> String { fn get_rust(&self) -> String {
match self { match self {
Postfix::FieldAccess(field) => format!(".{}", field.get_rust()), Postfix::FieldAccess(field, generics) => format!(
".{}{}",
field.get_rust(),
generics
.as_ref()
.map(|v| format!("::{}", v.get_rust()))
.unwrap_or_default()
),
Postfix::Call(args) => { Postfix::Call(args) => {
let args = args let args = args
@@ -227,24 +301,7 @@ impl GetRust for Postfix {
format!("[{}]", idx.get_rust()) format!("[{}]", idx.get_rust())
} }
Postfix::Binary(op, rhs) => { Postfix::As(ty) => format!(" as {}", ty.get_rust()),
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 => "||",
};
format!(" {} {}", op_str, rhs.get_rust())
}
} }
} }
} }
@@ -254,7 +311,6 @@ impl GetRust for [Postfix] {
self.iter().map(Postfix::get_rust).collect() self.iter().map(Postfix::get_rust).collect()
} }
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// ToRust — output-writing (top-level, statements, blocks) // ToRust — output-writing (top-level, statements, blocks)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -545,8 +601,17 @@ impl ToRust for Statement {
cg.add_indentedln(&format!("let {}{};", decl.get_rust(), init)); cg.add_indentedln(&format!("let {}{};", decl.get_rust(), init));
} }
Statement::VarAssign(VarAssignStmt { target, value }) => { Statement::Assign {
cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),)); target,
compound,
value,
} => {
cg.add_indentedln(&format!(
"{} {} {};",
target.get_rust(),
compound,
value.get_rust(),
));
} }
Statement::Match(expr, match_items) => { Statement::Match(expr, match_items) => {
@@ -639,6 +704,9 @@ impl ToRust for Statement {
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())),
} }
} }
} }
@@ -822,7 +890,7 @@ impl GetRust for Generics {
"<{}>", "<{}>",
self.0 self.0
.iter() .iter()
.map(|v| (true, v).get_rust()) .map(|v| (false, v).get_rust())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", ") .join(", ")
) )
@@ -836,9 +904,7 @@ impl GetRust for (bool, &Generic) {
Generic::Lifetime(name) => format!("'{}", name.get_rust()), Generic::Lifetime(name) => format!("'{}", name.get_rust()),
Generic::Type(name, requirements) => { Generic::Type(name, requirements) => {
name.get_rust() name.get_rust()
+ &(if !self.0 && requirements.len() == 0 { + &(if self.0 && requirements.len() != 0 {
String::new()
} else {
format!( format!(
": {}", ": {}",
requirements requirements
@@ -847,6 +913,8 @@ impl GetRust for (bool, &Generic) {
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("+") .join("+")
) )
} else {
String::new()
}) })
} }
} }