diff --git a/compiler/src/main.rs b/compiler/src/main.rs index 93156d5..4ab59fe 100644 --- a/compiler/src/main.rs +++ b/compiler/src/main.rs @@ -1,6 +1,6 @@ use clap::Parser; use compiler::compile; -use compiler::passes::parse::parse::{parse_program, PrettyParseError}; +use compiler::passes::parse::parse::PrettyParseError; use compiler::passes::validate::error::TypeError; use miette::{Diagnostic, IntoDiagnostic}; use std::fs; diff --git a/compiler/src/passes/parse/display.rs b/compiler/src/passes/parse/display.rs index fa78e91..e813ef2 100644 --- a/compiler/src/passes/parse/display.rs +++ b/compiler/src/passes/parse/display.rs @@ -1,19 +1,40 @@ -use std::fmt::{Display, Formatter}; +use crate::passes::parse::{Def, Expr, Op, TypeDef}; use indenter::indented; use itertools::Itertools; -use crate::passes::parse::{Def, Expr, Op}; use std::fmt::Write; +use std::fmt::{Display, Formatter}; -impl Display for Def { +impl Display + for Def +{ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - Def::Fn { sym, params, typ, bdy } => { + Def::Fn { + sym, + params, + typ, + bdy, + } => { writeln!(f, "fn {sym}({}) -> {typ} {{", params.iter().format(", "))?; writeln!(indented(f), "{bdy}")?; writeln!(f, "}}")?; Ok(()) } - Def::TypeDef { sym, def } => todo!(), + Def::TypeDef { sym, def } => match def { + TypeDef::Struct { fields } => { + writeln!(f, "struct {sym} {{")?; + writeln!( + indented(f), + "{}", + fields + .iter() + .map(|(sym, bnd)| format!("{sym}: {bnd},")) + .format("\n") + )?; + writeln!(f, "}}") + } + TypeDef::Enum { .. } => todo!(), + }, } } } @@ -21,17 +42,43 @@ impl Display for Def Display for Expr<'_, IdentVars, IdentFields> { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - Expr::Lit { val } => write!(f, "{val}"), - Expr::Var { sym } => write!(f, "{sym}"), - Expr::Prim { op: Op::Read, ..} => write!(f, "read()"), - Expr::Prim { op: Op::Print, args} => write!(f, "print({})", args[0].inner), - Expr::Prim { op, args } if args.len() == 1 => write!(f, "({op} {})", args[0].inner), - Expr::Prim { op, args } if args.len() == 2 => write!(f, "({} {op} {})", args[0].inner, args[1].inner), - Expr::Prim { .. } => unreachable!(), - Expr::Let { sym, mutable, bnd, bdy } => { - writeln!(f, "let {}{sym} = {bnd};", if *mutable { "mut " } else { "" })?; + Expr::Lit { val } => { + write!(f, "{val}") + } + Expr::Var { sym } => { + write!(f, "{sym}") + } + Expr::Prim { op: Op::Read, .. } => { + write!(f, "read()") + } + Expr::Prim { + op: Op::Print, + args, + } => { + write!(f, "print({})", args[0].inner) + } + Expr::Prim { op, args } if args.len() == 1 => { + write!(f, "({op} {})", args[0].inner) + } + Expr::Prim { op, args } if args.len() == 2 => { + write!(f, "({} {op} {})", args[0].inner, args[1].inner) + } + Expr::Prim { .. } => { + unreachable!() + } + Expr::Let { + sym, + mutable, + bnd, + bdy, + } => { + writeln!( + f, + "let {}{sym} = {bnd};", + if *mutable { "mut " } else { "" } + )?; write!(f, "{bdy}") - }, + } Expr::If { cnd, thn, els } => { writeln!(f, "if {cnd} {{")?; writeln!(indented(f), "{thn}")?; @@ -39,17 +86,47 @@ impl Display for Expr<'_, IdentVars, I writeln!(indented(f), "{els}")?; write!(f, "}}") } - Expr::Apply { .. } => todo!(), - Expr::Loop { .. } => todo!(), - Expr::Break { .. } => todo!(), - Expr::Continue => todo!(), - Expr::Return { .. } => todo!(), - Expr::Seq { .. } => todo!(), - Expr::Assign { .. } => todo!(), - Expr::Struct { .. } => todo!(), + Expr::Apply { fun, args } => { + write!(f, "{fun}({})", args.iter().format(", ")) + } + Expr::Loop { bdy } => { + writeln!(f, "loop {{")?; + writeln!(indented(f), "{bdy}")?; + write!(f, "}}") + } + Expr::Break { bdy } => { + write!(f, "break {bdy}") + } + Expr::Continue => { + write!(f, "continue") + } + Expr::Return { bdy } => { + write!(f, "return {bdy}") + } + Expr::Seq { stmt, cnt } => { + writeln!(f, "{stmt};")?; + write!(f, "{cnt}") + } + Expr::Assign { sym, bnd } => { + write!(f, "{sym} = {bnd}") + } + Expr::Struct { sym, fields } => { + writeln!(f, "{sym} {{")?; + writeln!( + indented(f), + "{}", + fields + .iter() + .map(|(sym, bnd)| format!("{sym}: {bnd},")) + .format("\n") + )?; + write!(f, "}}") + } + Expr::AccessField { strct, field } => { + write!(f, "{strct}.{field}") + } Expr::Variant { .. } => todo!(), - Expr::AccessField { .. } => todo!(), Expr::Switch { .. } => todo!(), } } -} \ No newline at end of file +} diff --git a/compiler/src/passes/parse/mod.rs b/compiler/src/passes/parse/mod.rs index 1f1c47a..64b096c 100644 --- a/compiler/src/passes/parse/mod.rs +++ b/compiler/src/passes/parse/mod.rs @@ -4,23 +4,23 @@ #[rustfmt::skip] #[allow(clippy::all, clippy::pedantic)] mod grammar; +mod display; pub mod interpreter; pub mod parse; #[cfg(test)] mod tests; pub mod types; -mod display; use crate::utils::gen_sym::UniqueSym; use derive_more::Display; use functor_derive::Functor; +use itertools::Itertools; use std::fmt::{Display, Formatter}; use types::Type; -use itertools::Itertools; /// A parsed program with global definitions and an entry point. #[derive(Display)] -#[display(fmt = "{}", r#"defs.into_iter().format("\n\n")"#)] +#[display(fmt = "{}", r#"defs.iter().format("\n")"#)] pub struct PrgParsed<'p> { /// The global program definitions. pub defs: Vec>, @@ -81,8 +81,7 @@ impl Def { /// /// Parameters are generic and can use symbols that are either `&str` or /// [`UniqueSym`](crate::utils::gen_sym::UniqueSym) for all passes after uniquify. -#[derive(Clone)] -#[derive(Display)] +#[derive(Clone, Display)] #[display(bound = "A: Display")] #[display(fmt = "{}{sym}: {typ}", r#"if *mutable { "mut " } else { "" }"#)] pub struct Param { @@ -256,38 +255,55 @@ impl Display for Spanned { #[derive(Display)] pub enum Op { /// Read signed integer from stdin. + #[display(fmt = "")] Read, /// Print signed integer to stdout. + #[display(fmt = "")] Print, /// Integer addition. + #[display(fmt = "+")] Plus, /// Integer subtraction or negation. + #[display(fmt = "-")] Minus, /// Integer multiplication. + #[display(fmt = "*")] Mul, /// Integer division. + #[display(fmt = "/")] Div, /// Modulo operation. + #[display(fmt = "%")] Mod, /// Logical AND. + #[display(fmt = "&&")] LAnd, /// Logical OR, + #[display(fmt = "||")] LOr, /// Logical NOT. + #[display(fmt = "!")] Not, /// XOR operation. + #[display(fmt = "^")] Xor, /// Greater Than comparison. + #[display(fmt = ">")] GT, /// Greater Than or Equal To comparison. + #[display(fmt = ">=")] GE, /// Equality comparison. Operates on `Int` and `Bool`. + #[display(fmt = "==")] EQ, /// Less Than or Equal To comparison. + #[display(fmt = "<=")] LE, /// Less Than comparison. + #[display(fmt = "<")] LT, /// Inequality comparison. Operates on `Int` and `Bool`. + #[display(fmt = "!=")] NE, } diff --git a/compiler/src/passes/parse/tests.rs b/compiler/src/passes/parse/tests.rs index 2e11479..39987c4 100644 --- a/compiler/src/passes/parse/tests.rs +++ b/compiler/src/passes/parse/tests.rs @@ -7,9 +7,6 @@ fn parse([test]: [&str; 1]) { let result = parse_program(test); - print!("{}", result.unwrap()); - panic!(); - match (result, expected_error) { (Ok(_), None) => {} (Err(error), None) => {