use arcstr::Substr; use derive_more::Deref; use indexmap::IndexMap; use std::ops::Range; use std::sync::Arc; #[derive(Debug, Deref)] pub struct Ident(pub Substr); #[derive(Debug, Deref)] pub struct Import(pub Expr); #[derive(Debug)] pub struct Number { pub text: Substr, pub r#type: Option, } #[derive(derive_more::Debug)] pub enum Expr { #[debug("uninit")] Uninit(Substr), #[debug("Ident({:?})", _0.0)] Ident(Ident), #[debug("{_0:?}")] Number(Number), String(Substr), #[debug("{_0:?}")] Binary(Box), Index(Box), Access(Box), Deref(Box), Tuple(Vec), List(Vec), Struct(Box), #[debug("{_0:?}")] Block(Arc), #[debug("{_0:?}")] Func(Arc), #[debug("{_0:?}")] Type(Box), #[debug("{_0:?}")] ConstDecl(Box), #[debug("{_0:?}")] VarDecl(Box), #[debug("{_0:?}")] For(Box), #[debug("{_0:?}")] While(Box), #[debug("{_0:?}")] If(Box), Call { func: Box, args: Vec, }, } impl Expr { pub fn range(&self) -> Range { match self { Self::Ident(e) => e.range(), Self::Access(e) => e.range(), Self::Number(e) => e.text.range(), _ => todo!("{self:?}"), } } } #[derive(Debug)] pub struct BinaryExpr { pub lhs: Expr, pub op: BinaryOp, pub rhs: Expr, } #[derive(Debug)] pub struct IndexingExpr { pub value: Expr, pub index: Expr, } #[derive(Debug)] pub struct AccessExpr { pub value: Expr, pub field: Ident, } impl AccessExpr { pub fn range(&self) -> Range { self.value.range().start..self.field.0.range().end } } #[rustfmt::skip] #[derive(derive_more::Debug)] pub enum BinaryOp { #[debug("{_0}")] Add(Substr), #[debug("{_0}")] Sub(Substr), #[debug("{_0}")] Mul(Substr), #[debug("{_0}")] Div(Substr), #[debug("{_0}")] Mod(Substr), #[debug("{_0}")] Eq(Substr), #[debug("{_0}")] Ne(Substr), #[debug("{_0}")] Lt(Substr), #[debug("{_0}")] Gt(Substr), #[debug("{_0}")] Le(Substr), #[debug("{_0}")] Ge(Substr), #[debug("{_0}")] Range(Substr), #[debug("{_0}")] Assign(Substr), #[debug("{_0}")] Cast(Substr), } #[derive(Debug)] pub enum Type { Ptr { base: Expr, mutable: Option }, Struct(Struct), } #[derive(Debug)] pub struct ConstDecl { pub names: NamePattern, pub r#type: Option, pub value: Expr, } #[derive(Debug)] pub struct VarDecl { pub names: NamePattern, pub r#type: Option, pub value: Expr, } #[derive(Debug)] pub enum NamePattern { Single(Ident), Tuple(Vec), List(Vec), } impl NamePattern { pub fn as_slice(&self) -> &[Ident] { match self { NamePattern::Single(ident) => std::slice::from_ref(ident), NamePattern::Tuple(idents) => idents.as_slice(), NamePattern::List(idents) => idents.as_slice(), } } } #[derive(Debug)] pub struct Function { pub text: Substr, pub args: Vec, pub ret: Option, pub block: Option>, } #[derive(Debug)] pub struct NameValuePair { pub name: Ident, pub value: Expr, } #[derive(Debug)] pub struct Struct { pub fields: Vec, } #[derive(Debug)] pub struct Field { pub name: Ident, pub ty: Expr, pub public: Option, pub mutable: Option, } #[derive(Debug)] pub struct StructCtor { pub r#type: Option, pub r#values: IndexMap, pub(crate) range: Range, } impl StructCtor { pub fn range(&self) -> Range { self.range.clone() } } #[derive(Debug)] pub struct Block(pub Vec); #[derive(Debug)] pub struct For { pub names: NamePattern, pub value: Expr, pub block: Block, } #[derive(Debug)] pub struct While { pub cond: Expr, pub block: Block, } #[derive(Debug)] pub struct If { pub cond: Expr, pub block: Block, pub else_: Option>, } #[derive(Debug)] pub enum Else { If(If), Block(Block), } #[derive(Debug)] pub struct CompilationUnit { pub imports: Vec, pub decls: Vec, }