use super::sys_call::SysCall; use crate::sys_call; use helpers::Span; use safer_ffi::prelude::*; use std::{borrow::Cow, ops::Deref}; use tokenizer::token::Number; #[derive(Debug, Eq, PartialEq, Clone)] pub enum Literal<'a> { Number(Number), String(Cow<'a, str>), Boolean(bool), } #[derive(Debug, Eq, PartialEq, Clone)] pub enum LiteralOr<'a, T> { Literal(Spanned>), Or(Spanned), } impl<'a, T: std::fmt::Display> std::fmt::Display for LiteralOr<'a, T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Literal(l) => write!(f, "{l}"), Self::Or(o) => write!(f, "{o}"), } } } impl<'a> std::fmt::Display for Literal<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Literal::Number(n) => write!(f, "{}", n), Literal::String(s) => write!(f, "\"{}\"", s), Literal::Boolean(b) => write!(f, "{}", if *b { 1 } else { 0 }), } } } #[derive(Debug, PartialEq, Eq)] pub enum BinaryExpression<'a> { Add(Box>>, Box>>), Multiply(Box>>, Box>>), Divide(Box>>, Box>>), Subtract(Box>>, Box>>), Exponent(Box>>, Box>>), Modulo(Box>>, Box>>), } impl<'a> std::fmt::Display for BinaryExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { BinaryExpression::Add(l, r) => write!(f, "({} + {})", l, r), BinaryExpression::Multiply(l, r) => write!(f, "({} * {})", l, r), BinaryExpression::Divide(l, r) => write!(f, "({} / {})", l, r), BinaryExpression::Subtract(l, r) => write!(f, "({} - {})", l, r), BinaryExpression::Exponent(l, r) => write!(f, "({} ** {})", l, r), BinaryExpression::Modulo(l, r) => write!(f, "({} % {})", l, r), } } } #[derive(Debug, PartialEq, Eq)] pub enum LogicalExpression<'a> { And(Box>>, Box>>), Or(Box>>, Box>>), Not(Box>>), Equal(Box>>, Box>>), NotEqual(Box>>, Box>>), GreaterThan(Box>>, Box>>), GreaterThanOrEqual(Box>>, Box>>), LessThan(Box>>, Box>>), LessThanOrEqual(Box>>, Box>>), } impl<'a> std::fmt::Display for LogicalExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { LogicalExpression::And(l, r) => write!(f, "({} && {})", l, r), LogicalExpression::Or(l, r) => write!(f, "({} || {})", l, r), LogicalExpression::Not(e) => write!(f, "(!{})", e), LogicalExpression::Equal(l, r) => write!(f, "({} == {})", l, r), LogicalExpression::NotEqual(l, r) => write!(f, "({} != {})", l, r), LogicalExpression::GreaterThan(l, r) => write!(f, "({} > {})", l, r), LogicalExpression::GreaterThanOrEqual(l, r) => write!(f, "({} >= {})", l, r), LogicalExpression::LessThan(l, r) => write!(f, "({} < {})", l, r), LogicalExpression::LessThanOrEqual(l, r) => write!(f, "({} <= {})", l, r), } } } #[derive(Debug, PartialEq, Eq)] pub struct AssignmentExpression<'a> { pub assignee: Box>>, pub expression: Box>>, } impl<'a> std::fmt::Display for AssignmentExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "({} = {})", self.assignee, self.expression) } } #[derive(Debug, PartialEq, Eq)] pub struct FunctionExpression<'a> { pub name: Spanned>, pub arguments: Vec>>, pub body: BlockExpression<'a>, } impl<'a> std::fmt::Display for FunctionExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "(fn {}({}) {{ {} }})", self.name, self.arguments .iter() .map(|e| e.to_string()) .collect::>() .join(", "), self.body ) } } #[derive(Debug, PartialEq, Eq)] pub struct BlockExpression<'a>(pub Vec>>); impl<'a> std::fmt::Display for BlockExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{{ {}; }}", self.0 .iter() .map(|e| e.to_string()) .collect::>() .join("; ") ) } } #[derive(Debug, PartialEq, Eq)] pub struct InvocationExpression<'a> { pub name: Spanned>, pub arguments: Vec>>, } impl<'a> std::fmt::Display for InvocationExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{}({})", self.name, self.arguments .iter() .map(|e| e.to_string()) .collect::>() .join(", ") ) } } #[derive(Debug, PartialEq, Eq)] pub struct MemberAccessExpression<'a> { pub object: Box>>, pub member: Spanned>, } impl<'a> std::fmt::Display for MemberAccessExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}.{}", self.object, self.member) } } #[derive(Debug, PartialEq, Eq)] pub struct MethodCallExpression<'a> { pub object: Box>>, pub method: Spanned>, pub arguments: Vec>>, } impl<'a> std::fmt::Display for MethodCallExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "{}.{}({})", self.object, self.method, self.arguments .iter() .map(|e| e.to_string()) .collect::>() .join(", ") ) } } #[derive(Debug, PartialEq, Eq)] pub enum LiteralOrVariable<'a> { Literal(Literal<'a>), Variable(Spanned>), } impl<'a> std::fmt::Display for LiteralOrVariable<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { LiteralOrVariable::Literal(l) => write!(f, "{}", l), LiteralOrVariable::Variable(v) => write!(f, "{}", v), } } } #[derive(Debug, PartialEq, Eq)] pub struct ConstDeclarationExpression<'a> { pub name: Spanned>, pub value: LiteralOr<'a, SysCall<'a>>, } impl<'a> ConstDeclarationExpression<'a> { pub fn is_syscall_supported(call: &SysCall) -> bool { use sys_call::System; matches!(call, SysCall::System(sys) if matches!(sys, System::Hash(_))) } } impl<'a> std::fmt::Display for ConstDeclarationExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(const {} = {})", self.name, self.value) } } #[derive(Debug, PartialEq, Eq)] pub struct DeviceDeclarationExpression<'a> { /// any variable-like name pub name: Spanned>, /// The device port, ex. (db, d0, d1, d2, d3, d4, d5) pub device: Cow<'a, str>, } impl<'a> std::fmt::Display for DeviceDeclarationExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(device {} = {})", self.name, self.device) } } #[derive(Debug, PartialEq, Eq)] pub struct IfExpression<'a> { pub condition: Box>>, pub body: Spanned>, pub else_branch: Option>>>, } impl<'a> std::fmt::Display for IfExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(if ({}) {}", self.condition, self.body)?; if let Some(else_branch) = &self.else_branch { write!(f, " else {}", else_branch)?; } write!(f, ")") } } #[derive(Debug, PartialEq, Eq)] pub struct LoopExpression<'a> { pub body: Spanned>, } impl<'a> std::fmt::Display for LoopExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(loop {})", self.body) } } #[derive(Debug, PartialEq, Eq)] pub struct WhileExpression<'a> { pub condition: Box>>, pub body: BlockExpression<'a>, } #[derive(Debug, PartialEq, Eq)] pub struct TernaryExpression<'a> { pub condition: Box>>, pub true_value: Box>>, pub false_value: Box>>, } impl<'a> std::fmt::Display for TernaryExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "({} ? {} : {})", self.condition, self.true_value, self.false_value ) } } impl<'a> std::fmt::Display for WhileExpression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "(while {} {})", self.condition, self.body) } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Spanned { pub span: Span, pub node: T, } impl std::fmt::Display for Spanned where T: std::fmt::Display, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.node) } } impl Deref for Spanned { type Target = T; fn deref(&self) -> &Self::Target { &self.node } } #[derive(Debug, PartialEq, Eq)] pub enum Expression<'a> { Assignment(Spanned>), Binary(Spanned>), Block(Spanned>), Break(Span), ConstDeclaration(Spanned>), Continue(Span), Declaration(Spanned>, Box>>), DeviceDeclaration(Spanned>), Function(Spanned>), If(Spanned>), Invocation(Spanned>), Literal(Spanned>), Logical(Spanned>), Loop(Spanned>), MemberAccess(Spanned>), MethodCall(Spanned>), Negation(Box>>), Priority(Box>>), Return(Option>>>), Syscall(Spanned>), Ternary(Spanned>), Variable(Spanned>), While(Spanned>), } impl<'a> std::fmt::Display for Expression<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Expression::Assignment(e) => write!(f, "{}", e), Expression::Binary(e) => write!(f, "{}", e), Expression::Block(e) => write!(f, "{}", e), Expression::Break(_) => write!(f, "break"), Expression::ConstDeclaration(e) => write!(f, "{}", e), Expression::Continue(_) => write!(f, "continue"), Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e), Expression::DeviceDeclaration(e) => write!(f, "{}", e), Expression::Function(e) => write!(f, "{}", e), Expression::If(e) => write!(f, "{}", e), Expression::Invocation(e) => write!(f, "{}", e), Expression::Literal(l) => write!(f, "{}", l), Expression::Logical(e) => write!(f, "{}", e), Expression::Loop(e) => write!(f, "{}", e), Expression::MemberAccess(e) => write!(f, "{}", e), Expression::MethodCall(e) => write!(f, "{}", e), Expression::Negation(e) => write!(f, "(-{})", e), Expression::Priority(e) => write!(f, "({})", e), Expression::Return(e) => write!( f, "(return {})", if let Some(e) = e { e.to_string() } else { "".to_string() } ), Expression::Syscall(e) => write!(f, "{}", e), Expression::Ternary(e) => write!(f, "{}", e), Expression::Variable(id) => write!(f, "{}", id), Expression::While(e) => write!(f, "{}", e), } } }