// Copyright (c) 2022 Marceline Cramer // SPDX-License-Identifier: GPL-3.0-or-later use super::lexer::Token; #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct Ast<'a> { pub defs: Vec>, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum Definition<'a> { Struct { name: &'a str, members: Vec>, }, Function { associated_struct: Option<&'a str>, implementation: FnImpl<'a>, }, Interface { name: &'a str, functions: Vec>, }, Impl { structure: &'a str, interface: Option<&'a str>, functions: Vec>, }, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct FnImpl<'a> { pub def: FnDef<'a>, pub body: BranchBody<'a>, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct FnDef<'a> { pub mutable: bool, pub name: &'a str, pub signature: FnSig<'a>, } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct StructMember<'a> { pub type_name: &'a str, pub name: &'a str, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct FnSig<'a> { pub args: Vec>, pub return_type: Option<&'a str>, } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct FnArg<'a> { pub type_name: &'a str, pub name: Option<&'a str>, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct BranchBody<'a> { pub statements: Vec>, pub tail_expr: Option>>, } type ExprPair<'a> = Box<(Expr<'a>, Expr<'a>)>; #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum Expr<'a> { BinaryOp(BinaryOp, ExprPair<'a>), UnaryOp(UnaryOp, Box>), Literal(Literal<'a>), Local(&'a str), Member(&'a str, Box>), SelfMember(&'a str), Group(Box>), FnCall(Box>, Vec>), If(IfExpr<'a>), } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum BinaryOp { Add, Sub, Mul, Div, Assign, BoolOr, BoolAnd, BitOr, BitAnd, BitXor, Less, LessEq, Greater, GreaterEq, Eq, Neq, } impl BinaryOp { pub fn from_token(tok: Token) -> Option { use BinaryOp::*; use Token::*; match tok { OpAdd => Some(Add), OpSub => Some(Sub), OpMul => Some(Mul), OpDiv => Some(Div), OpAssign => Some(Assign), OpBoolOr => Some(BoolOr), OpBoolAnd => Some(BoolAnd), OpBitOr => Some(BitOr), OpBitAnd => Some(BitAnd), OpBitXor => Some(BitXor), OpLess => Some(Less), OpLessEq => Some(LessEq), OpGreater => Some(Greater), OpGreaterEq => Some(GreaterEq), OpEq => Some(Eq), OpNeq => Some(Neq), _ => None, } } } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum UnaryOp { BoolNot, BitNot, Negate, } impl UnaryOp { pub fn from_token(tok: Token) -> Option { use Token::*; use UnaryOp::*; match tok { OpBoolNot => Some(BoolNot), OpBitNot => Some(BitNot), OpSub => Some(Negate), _ => None, } } } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum Literal<'a> { BinaryInteger(&'a str), OctalInteger(&'a str), HexInteger(&'a str), DecimalInteger(&'a str), DecimalFloat(&'a str), String(&'a str), Boolean(bool), } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub enum Statement<'a> { Expr(Expr<'a>), If(IfStmt<'a>), While { test_expr: Expr<'a>, loop_body: BranchBody<'a>, }, Let { var: &'a str, mutable: bool, expr: Expr<'a>, }, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct IfExpr<'a> { pub test_expr: Box>, pub then_body: BranchBody<'a>, pub else_body: BranchBody<'a>, } #[derive(Clone, Debug, Eq, Hash, PartialEq)] pub struct IfStmt<'a> { pub test_expr: Expr<'a>, pub then_body: BranchBody<'a>, pub else_body: Option>, } impl<'a> IfStmt<'a> { pub fn to_expr(self) -> IfExpr<'a> { let Self { test_expr, then_body, else_body, } = self; IfExpr { test_expr: Box::new(test_expr), then_body, else_body: else_body.unwrap(), } } }