use crate::compiler::parser::lexer::TokenType;
use crate::compiler::parser::pointer::P;
use std::fmt::{Display, Formatter};
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum Stmt {
Expr(P<Expr>),
Semi(P<Expr>),
Match(Vec<P<Atom>>), Return(Vec<P<Expr>>),
BangBang,
Empty,
}
impl Display for Stmt {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Stmt::Expr(_) => {
write!(f, "ExprStmt")
}
Stmt::Semi(_) => {
write!(f, "SemiStmt")
}
Stmt::Match(_) => {
write!(f, "MatchStmt")
}
Stmt::Return(_) => {
write!(f, "Return")
}
Stmt::BangBang => {
write!(f, "BangBang")
}
Stmt::Empty => {
write!(f, "Empty")
}
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum ExprKind {
Tuple(Vec<P<Expr>>),
Unary(UnaryOpToken, P<Expr>),
Binary(BinOpToken, P<Expr>, P<Expr>),
Assignment(P<Expr>, P<Expr>),
Literal(LiteralToken),
Variable(u8),
ValueDiscard,
FunCall(u8, Vec<NamedParameter>),
FieldAccess(P<Expr>, u8),
}
impl Display for ExprKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ExprKind::Tuple(_) => {
write!(f, "Tuple")
}
ExprKind::Unary(op, _) => {
write!(f, "{}", op)
}
ExprKind::Binary(op, _, _) => {
write!(f, "{}", op)
}
ExprKind::Assignment(_, _) => {
write!(f, "Assignment")
}
ExprKind::Literal(lit) => {
write!(f, "{}", lit)
}
ExprKind::Variable(id) => {
write!(f, "var({})", *id)
}
ExprKind::ValueDiscard => {
write!(f, "discard")
}
ExprKind::FunCall(name, _) => {
write!(f, "Call({})", name)
}
ExprKind::FieldAccess(_, _) => {
write!(f, "FieldAccess")
}
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Expr {
pub(crate) kind: ExprKind,
pub(crate) span: Span,
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Block {
pub(crate) stmts: Vec<Stmt>,
pub(crate) span: Span,
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct NamedParameter {
pub(crate) name: Option<u8>,
pub(crate) value: P<Expr>,
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Atom {
pub(crate) kind: AtomKind,
pub(crate) span: Span,
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum AtomKind {
FunCall(u8, Vec<NamedParameter>),
Map(u8, Vec<NamedParameter>, MapTarget),
Block(P<Block>),
Return(Vec<P<Expr>>),
}
impl Display for AtomKind {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
AtomKind::FunCall(name, _) => {
write!(f, "Call({})", name)
}
AtomKind::Map(name, _, map_to) => {
write!(f, "Map({})->[", name)?;
match map_to {
MapTarget::Tuple(t) => write!(f, "Tuple({})", t.len())?,
MapTarget::Type(type_name, _) => write!(f, "Type({})", type_name)?,
}
write!(f, "]")?;
Ok(())
}
AtomKind::Block(_) => {
write!(f, "Block")
}
AtomKind::Return(_) => {
write!(f, "Generate")
}
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub(crate) enum MapTarget {
Tuple(Vec<P<Expr>>),
Type(u8, Vec<NamedParameter>),
}
#[derive(Debug, PartialEq, Default, Clone)]
pub(crate) struct FunctionDefinition {
pub(crate) name: String,
pub(crate) formal_arguments: Vec<P<Expr>>,
pub(crate) body: Vec<Stmt>,
}
#[derive(Debug, PartialEq, Default, Clone)]
pub(crate) struct TypeDefinition {
pub(crate) name: String,
pub(crate) fields: Vec<TypedVariableDefinition>,
}
impl Display for TypeDefinition {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "type {}:{{", self.name)?;
for (pos, field) in self.fields.iter().enumerate() {
write!(f, "({}:{})", field.name, field.type_name)?;
if pos < self.fields.len() {
write!(f, ",")?
}
}
Ok(())
}
}
#[derive(Debug, PartialEq, Default, Clone)]
pub(crate) struct TypedVariableDefinition {
pub(crate) name: String,
pub(crate) type_name: TypeName,
}
impl Display for TypedVariableDefinition {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.name, self.type_name)
}
}
#[derive(Debug, PartialEq, Default, Clone)]
pub(crate) struct TypeName {
pub(crate) name: String,
}
impl Display for TypeName {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name)
}
}
#[derive(Debug, Clone, Copy)]
pub struct Span {
pub(crate) line: usize,
pub(crate) offset: usize, pub(crate) length: usize,
}
impl Display for Span {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "line: {}, position: {}", self.line, self.offset)
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum BinOpToken {
Plus,
Minus,
Star,
Slash,
GreaterThan,
LessThan,
Equals,
NotEquals,
And,
Or,
}
impl Display for BinOpToken {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
BinOpToken::Plus => {
write!(f, "Add")
}
BinOpToken::Minus => {
write!(f, "Subtract")
}
BinOpToken::Star => {
write!(f, "Multiply")
}
BinOpToken::Slash => {
write!(f, "Divide")
}
BinOpToken::GreaterThan => {
write!(f, "GreaterThan")
}
BinOpToken::LessThan => {
write!(f, "LessThan")
}
BinOpToken::Equals => {
write!(f, "Equals")
}
BinOpToken::NotEquals => {
write!(f, "NotEquals")
}
BinOpToken::And => {
write!(f, "And")
}
BinOpToken::Or => {
write!(f, "Or")
}
}
}
}
impl TryFrom<TokenType> for BinOpToken {
type Error = TokenType;
fn try_from(value: TokenType) -> Result<Self, Self::Error> {
match value {
TokenType::Plus => Ok(BinOpToken::Plus),
TokenType::Minus => Ok(BinOpToken::Minus),
TokenType::Star => Ok(BinOpToken::Star),
TokenType::Slash => Ok(BinOpToken::Slash),
TokenType::GreaterThan => Ok(BinOpToken::GreaterThan),
TokenType::LessThan => Ok(BinOpToken::LessThan),
TokenType::EqualsEquals => Ok(BinOpToken::Equals),
TokenType::BangEquals => Ok(BinOpToken::NotEquals),
TokenType::AmpAmp => Ok(BinOpToken::And),
TokenType::PipePipe => Ok(BinOpToken::Or),
_ => Err(value),
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum UnaryOpToken {
Bang,
Minus,
}
impl Display for UnaryOpToken {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
UnaryOpToken::Bang => {
write!(f, "Not")
}
UnaryOpToken::Minus => {
write!(f, "Minus")
}
}
}
}
pub(crate) const DUMMY_SPAN: Span = Span {
line: 0,
offset: 0,
length: 0,
};
impl PartialEq for Span {
fn eq(&self, other: &Self) -> bool {
if self.line == DUMMY_SPAN.line && self.offset == DUMMY_SPAN.offset {
return true;
}
if other.line == DUMMY_SPAN.line && other.offset == DUMMY_SPAN.offset {
return true;
}
return self.line == other.line && self.offset == other.offset;
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum LiteralToken {
True,
False,
Integer(u8),
Float(u8),
StringLiteral(u8),
}
impl Display for LiteralToken {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
LiteralToken::True => Display::fmt("True", f),
LiteralToken::False => Display::fmt("False", f),
LiteralToken::Integer(integer) => Display::fmt(integer, f),
LiteralToken::Float(float) => Display::fmt(float, f),
LiteralToken::StringLiteral(string) => Display::fmt(string, f),
}
}
}