Merge pull request #31 from mist-go/assignments-expressions
Improved Assignments & expressions
This commit is contained in:
@@ -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");
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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>);
|
||||||
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>,
|
||||||
|
}
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user