Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix std::fmt::Display for abort expressions #830

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
82 changes: 51 additions & 31 deletions src/parser/ast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{
collections::BTreeMap,
fmt,
fmt::{self, Write},
hash::{Hash, Hasher},
iter::IntoIterator,
ops::Deref,
Expand Down Expand Up @@ -318,7 +318,7 @@ impl AsRef<str> for Ident {

impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
write!(f, "{}", &self.0)
}
}

Expand Down Expand Up @@ -357,9 +357,9 @@ impl fmt::Display for Literal {
match self {
String(v) => write!(f, r#""{v}""#),
RawString(v) => write!(f, "s'{v}'"),
Integer(v) => v.fmt(f),
Float(v) => v.fmt(f),
Boolean(v) => v.fmt(f),
Integer(v) => write!(f, "{v}"),
Float(v) => write!(f, "{:?}", v.as_ref()),
Boolean(v) => write!(f, "{v}"),
Regex(v) => write!(f, "r'{v}'"),
Timestamp(v) => write!(f, "t'{v}'"),
Null => f.write_str("null"),
Expand Down Expand Up @@ -389,9 +389,11 @@ impl fmt::Display for Container {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Container::{Array, Block, Group, Object};

let width = f.width().unwrap_or_default() + 4;

match self {
Group(v) => v.fmt(f),
Block(v) => v.fmt(f),
Block(v) => f.write_fmt(format_args!("{:width$}", v)),
Array(v) => v.fmt(f),
Object(v) => v.fmt(f),
}
Expand Down Expand Up @@ -442,14 +444,19 @@ impl fmt::Display for Block {

let mut iter = self.0.iter().peekable();
while let Some(expr) = iter.next() {
f.write_str("\t")?;
(0..f.width().unwrap_or_default()).try_for_each(|_| f.write_char(' '))?;
expr.fmt(f)?;
if iter.peek().is_some() {
f.write_str("\n")?;
}
}

f.write_str("\n}")
f.write_str("\n")?;
f.write_fmt(format_args!(
"{:>width$}",
"}",
width = f.width().unwrap_or(4) - 3
))
}
}

Expand Down Expand Up @@ -622,12 +629,14 @@ impl fmt::Display for IfStatement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("if ")?;
self.predicate.fmt(f)?;

let width = f.width().unwrap_or_default() + 4;
f.write_str(" ")?;
self.if_node.fmt(f)?;
f.write_fmt(format_args!("{:width$}", self.if_node,))?;

if let Some(alt) = &self.else_node {
f.write_str(" else")?;
alt.fmt(f)?;
f.write_str(" else ")?;
f.write_fmt(format_args!("{:width$}", alt))?;
}

Ok(())
Expand Down Expand Up @@ -693,7 +702,13 @@ pub struct Op(pub Box<Node<Expr>>, pub Node<Opcode>, pub Box<Node<Expr>>);

impl fmt::Display for Op {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {} {}", self.0, self.1, self.2)
f.write_fmt(format_args!(
"{:width$} {:width$} {:width$}",
self.0,
self.1,
self.2,
width = f.width().unwrap_or_default()
))
}
}

Expand Down Expand Up @@ -724,7 +739,7 @@ pub enum Opcode {

impl fmt::Display for Opcode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.as_str().fmt(f)
write!(f, "{}", self.as_str())
}
}

Expand Down Expand Up @@ -848,9 +863,12 @@ impl fmt::Display for Assignment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Assignment::{Infallible, Single};

let width = f.width().unwrap_or_default();
match self {
Single { target, op, expr } => write!(f, "{target} {op} {expr}"),
Infallible { ok, err, op, expr } => write!(f, "{ok}, {err} {op} {expr}"),
Single { target, op, expr } => f.write_fmt(format_args!("{target} {op} {expr:width$}")),
Infallible { ok, err, op, expr } => {
f.write_fmt(format_args!("{ok}, {err} {op} {expr:width$}"))
}
}
}
}
Expand Down Expand Up @@ -951,7 +969,14 @@ pub struct Query {

impl fmt::Display for Query {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", self.target, self.path)
let target = format!("{}", self.target);
let path = format!("{}", self.path);

if target == "." && path.starts_with(".") {
write!(f, "{path}")
} else {
write!(f, "{target}{path}")
}
}
}

Expand Down Expand Up @@ -1020,6 +1045,9 @@ pub struct FunctionCall {
impl fmt::Display for FunctionCall {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.ident.fmt(f)?;
if self.abort_on_error {
f.write_str("!")?;
}
f.write_str("(")?;

let mut iter = self.arguments.iter().peekable();
Expand All @@ -1034,7 +1062,6 @@ impl fmt::Display for FunctionCall {
f.write_str(")")?;

if let Some(closure) = &self.closure {
f.write_str(" ")?;
closure.fmt(f)?;
}

Expand Down Expand Up @@ -1110,7 +1137,7 @@ pub struct FunctionClosure {

impl fmt::Display for FunctionClosure {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("-> |")?;
f.write_str(" -> |")?;

let mut iter = self.variables.iter().peekable();
while let Some(var) = iter.next() {
Expand All @@ -1121,18 +1148,10 @@ impl fmt::Display for FunctionClosure {
}
}

f.write_str("| {\n")?;

let mut iter = self.block.0.iter().peekable();
while let Some(expr) = iter.next() {
f.write_str("\t")?;
expr.fmt(f)?;
if iter.peek().is_some() {
f.write_str("\n")?;
}
}
f.write_str("| ")?;

f.write_str("\n}")
let width = f.width().unwrap_or_default() + 4;
f.write_fmt(format_args!("{:width$}", self.block))
}
}

Expand Down Expand Up @@ -1194,7 +1213,8 @@ impl Not {

impl fmt::Display for Not {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "!{}", self.1)
let width = f.width().unwrap_or_default();
write!(f, "!{:width$}", self.1)
}
}

Expand All @@ -1219,7 +1239,7 @@ impl fmt::Display for Abort {
&self
.message
.as_ref()
.map_or_else(|| "abort".to_owned(), |m| format!("abort: {m}")),
.map_or_else(|| "abort".to_owned(), |m| format!("abort {m}")),
)
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/parser/template_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ pub enum StringSegment {
impl fmt::Display for StringSegment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
StringSegment::Literal(s, _) => write!(f, "{s}"),
StringSegment::Literal(s, _) => {
let s = format!("{s:?}");
let len = s.len();

write!(f, "{}", &s.as_str()[1..len - 1])
}
StringSegment::Template(s, _) => write!(f, "{{{{ {s} }}}}"),
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/path/owned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ impl From<&OwnedValuePath> for String {
for (i, segment) in owned.segments.iter().enumerate() {
match segment {
OwnedSegment::Field(field) => {
serialize_field(&mut output, field.as_ref(), (i != 0).then_some("."))
serialize_field(&mut output, field.as_ref(), Some("."))
}
OwnedSegment::Index(index) => {
write!(output, "[{index}]").expect("Could not write to string")
Expand Down
Loading