157 lines
5.0 KiB
Rust
157 lines
5.0 KiB
Rust
use crate::syntax::ast::{Expression, Program, Statement, Value};
|
|
use pretty::{DocAllocator, DocBuilder, Pretty};
|
|
|
|
use super::{ConstantType, TopLevel};
|
|
|
|
impl<'a, 'b, D, A> Pretty<'a, D, A> for &'b Program
|
|
where
|
|
A: 'a,
|
|
D: ?Sized + DocAllocator<'a, A>,
|
|
{
|
|
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
|
|
let mut result = allocator.nil();
|
|
|
|
for tl in self.items.iter() {
|
|
result = result
|
|
.append(tl.pretty(allocator))
|
|
.append(allocator.text(";"))
|
|
.append(allocator.hardline());
|
|
}
|
|
|
|
result
|
|
}
|
|
}
|
|
|
|
impl<'a, 'b, D, A> Pretty<'a, D, A> for &'b TopLevel
|
|
where
|
|
A: 'a,
|
|
D: ?Sized + DocAllocator<'a, A>,
|
|
{
|
|
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
|
|
match self {
|
|
TopLevel::Statement(stmt) => stmt.pretty(allocator),
|
|
TopLevel::Function(name, arg_names, body) => allocator
|
|
.text("function")
|
|
.append(allocator.space())
|
|
.append(allocator.text(name.to_string()))
|
|
.append(
|
|
allocator
|
|
.intersperse(
|
|
arg_names.iter().map(|x| allocator.text(x.to_string())),
|
|
CommaSep {},
|
|
)
|
|
.parens(),
|
|
)
|
|
.append(allocator.space())
|
|
.append(body.pretty(allocator)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, 'b, D, A> Pretty<'a, D, A> for &'b Statement
|
|
where
|
|
A: 'a,
|
|
D: ?Sized + DocAllocator<'a, A>,
|
|
{
|
|
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
|
|
match self {
|
|
Statement::Binding(_, var, expr) => allocator
|
|
.text(var.to_string())
|
|
.append(allocator.space())
|
|
.append(allocator.text("="))
|
|
.append(allocator.space())
|
|
.append(expr.pretty(allocator)),
|
|
Statement::Print(_, var) => allocator
|
|
.text("print")
|
|
.append(allocator.space())
|
|
.append(allocator.text(var.to_string())),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, 'b, D, A> Pretty<'a, D, A> for &'b Expression
|
|
where
|
|
A: 'a,
|
|
D: ?Sized + DocAllocator<'a, A>,
|
|
{
|
|
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
|
|
match self {
|
|
Expression::Value(_, val) => val.pretty(allocator),
|
|
Expression::Reference(_, var) => allocator.text(var.to_string()),
|
|
Expression::Cast(_, t, e) => allocator
|
|
.text(t.clone())
|
|
.angles()
|
|
.append(e.pretty(allocator)),
|
|
Expression::Primitive(_, op, exprs) if exprs.len() == 1 => allocator
|
|
.text(op.to_string())
|
|
.append(exprs[0].pretty(allocator)),
|
|
Expression::Primitive(_, op, exprs) if exprs.len() == 2 => {
|
|
let left = exprs[0].pretty(allocator);
|
|
let right = exprs[1].pretty(allocator);
|
|
|
|
left.append(allocator.space())
|
|
.append(allocator.text(op.to_string()))
|
|
.append(allocator.space())
|
|
.append(right)
|
|
.parens()
|
|
}
|
|
Expression::Primitive(_, op, exprs) => {
|
|
let call = allocator.text(op.to_string());
|
|
let args = exprs.iter().map(|x| x.pretty(allocator));
|
|
let comma_sepped_args = allocator.intersperse(args, CommaSep {});
|
|
call.append(comma_sepped_args.parens())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, 'b, D, A> Pretty<'a, D, A> for &'b Value
|
|
where
|
|
A: 'a,
|
|
D: ?Sized + DocAllocator<'a, A>,
|
|
{
|
|
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
|
|
match self {
|
|
Value::Number(opt_base, ty, value) => {
|
|
let value_str = match opt_base {
|
|
None => format!("{}{}", value, type_suffix(ty)),
|
|
Some(2) => format!("0b{:b}{}", value, type_suffix(ty)),
|
|
Some(8) => format!("0o{:o}{}", value, type_suffix(ty)),
|
|
Some(10) => format!("0d{}{}", value, type_suffix(ty)),
|
|
Some(16) => format!("0x{:x}{}", value, type_suffix(ty)),
|
|
Some(_) => format!("!!{:x}{}!!", value, type_suffix(ty)),
|
|
};
|
|
|
|
allocator.text(value_str)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn type_suffix(x: &Option<ConstantType>) -> &'static str {
|
|
match x {
|
|
None => "",
|
|
Some(ConstantType::I8) => "i8",
|
|
Some(ConstantType::I16) => "i16",
|
|
Some(ConstantType::I32) => "i32",
|
|
Some(ConstantType::I64) => "i64",
|
|
Some(ConstantType::U8) => "u8",
|
|
Some(ConstantType::U16) => "u16",
|
|
Some(ConstantType::U32) => "u32",
|
|
Some(ConstantType::U64) => "u64",
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
struct CommaSep {}
|
|
|
|
impl<'a, D, A> Pretty<'a, D, A> for CommaSep
|
|
where
|
|
A: 'a,
|
|
D: ?Sized + DocAllocator<'a, A>,
|
|
{
|
|
fn pretty(self, allocator: &'a D) -> DocBuilder<'a, D, A> {
|
|
allocator.text(",").append(allocator.space())
|
|
}
|
|
}
|