1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! Implementation of Display trait for abstract syntax tree.

use std::fmt::{self, Write};

use ast::*;

impl fmt::Display for Program {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        write!(f, "{}", self.0.item)
    }
}

impl fmt::Display for Block {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        write!(f, "\n{{\n")?;
        for statement in &self.0 {
            write!(f, "{}\n", statement.item)?;
        }
        write!(f, "}}")?;
        Ok(())
    }
}

impl fmt::Display for Statement {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Statement::Expression(ref expr) => write!(f, "expr:{}", expr.item),
            Statement::Declare(ref ident, ref expr) => write!(f, "decl({}->{})",
                ident.item, expr.item),
            Statement::Assign(ref ident, ref expr) => write!(f, "assign({}->{})",
                ident.item, expr.item),
            Statement::FnDefine(FunctionDef { ref name, ref body, ref params, ref ret_type }) => {
                let mut pl = String::new();
                let mut first = true;
                for expr in params {
                    if first {
                        first = false;
                    } else {
                        write!(&mut pl, ",")?;
                    }
                    write!(&mut pl, "{}", expr.item)?;
                }
                write!(f, "def({}({}) -> {}) {}", name.item, pl, ret_type.item,
                    body.item)
            },
            Statement::Return(ref expr) => write!(f, "return({})", expr.item),
            Statement::Break(ref expr) => write!(f, "break({})", expr.item),
            Statement::Print(ref exprs) => {
                let mut out = "print(".to_string();
                let mut first = true;
                for expr in exprs {
                    if first {
                        first = false;
                    } else {
                        write!(&mut out, ",")?;
                    }
                    write!(&mut out, "{}", expr.item)?;
                }
                write!(f, "{})", out)
            }
        }
    }
}

impl fmt::Display for Parameter {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        write!(f, "{}: {}", self.name.item, self.ty.item)
    }
}

impl fmt::Display for Expression {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Expression::Literal(ref lit) => write!(f, "lit:{}", lit.item),
            Expression::Identifier(ref ident) => write!(f, "ident:{}", ident.item),
            Expression::Infix { ref op, ref left, ref right } =>
                write!(f, "infix:{}{}{}", left.item, op, right.item),
            Expression::Prefix { ref op, ref right } =>
                write!(f, "prefix:{}{}", op, right.item),
            Expression::Postfix { ref op, ref left } =>
                write!(f, "postfix:{}{}", left.item, op),
            Expression::Block(ref block) =>
                write!(f, "block:{}", block.item),
            Expression::FnCall { name: ref ident, ref args } => {
                let mut pl = String::new();
                let mut first = true;
                for expr in args {
                    if first {
                        first = false;
                    } else {
                        write!(&mut pl, ",")?;
                    }
                    write!(&mut pl, "{}", expr.item)?;
                }
                write!(f, "fn{{{}}}({})", ident.item, pl)
            }
            Expression::IfElse { ref cond, ref if_block, else_block: Some(ref elseb) } => {
                write!(f, "if({}){{{}}}{{{}}}", cond.item, if_block.item, elseb.item)
            },
            Expression::IfElse { ref cond, ref if_block, else_block: None } => {
                write!(f, "if({}){{{}}}", cond.item, if_block.item)
            },
            Expression::Loop { ref variant, ref set, ref body } => {
                match *variant {
                    Some(ref var) => write!(f, "for({}={}){{{}}}", var.item, set.item, body.item),
                    None => write!(f, "for({}){{{}}}", set.item, body.item),
                }
            }
        }
    }
}

impl fmt::Display for Set {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Set::Interval { ref start, ref end, end_inclusive, ref step } => {
                let end_bracket = if end_inclusive { "]" } else { ")" };
                write!(f, "[{}..{}..{}{}", start.item, step.item, end.item, end_bracket)
            }
        }
    }
}

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Literal::String(ref s) => write!(f, "\"{}\"", s),
            Literal::Float(ref fl) => write!(f, "{}", fl),
            Literal::Int(ref i) => write!(f, "{}", *i),
            Literal::Boolean(ref b) => write!(f, "{}", b),
        }
    }
}

impl fmt::Display for PrefixOp {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            PrefixOp::UnaryMinus => write!(f, "-"),
            PrefixOp::UnaryPlus => write!(f, "+"),
        }
    }
}

impl fmt::Display for InfixOp {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            InfixOp::Add => write!(f, "+"),
            InfixOp::Subtract => write!(f, "-"),
            InfixOp::Multiply => write!(f, "*"),
            InfixOp::Divide => write!(f, "/"),
            InfixOp::Power => write!(f, "^"),
            InfixOp::Comparison(op) => {
                match op {
                    CompareOp::LessThan => write!(f, "<"),
                    CompareOp::LessThanEqual => write!(f, "<="),
                    CompareOp::GreaterThan => write!(f, ">"),
                    CompareOp::GreaterThanEqual => write!(f, ">="),
                    CompareOp::Equal => write!(f, "=="),
                    CompareOp::NotEqual => write!(f, "!="),
                }
            }
        }
    }
}

impl fmt::Display for PostfixOp {
    fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            PostfixOp::Conjugate => write!(f, "`"),
            PostfixOp::Imaginary => write!(f, "i"),
        }
    }
}