use std::fmt::{Display, Formatter, Result};
use {Block, Comment, Statement};
#[cfg(test)]
mod tests {
use {Argument, Assignment, Block, Class, Function, FunctionCall, KeywordArgument, Statement};
#[test]
fn it_makes_a_class() {
let mut program = Block::new();
let mut class = Class::new("Greeter", &program);
class.inherit_from("Exception");
class.add_docstring("Greeter is a class to say Hello!");
let arguments = vec![
Argument::new("self", None, None, None),
Argument::new("name", Some("\"World\""), Some("str"), Some("The name to greet")),
];
let mut init = Function::new("__init__", arguments, &class.block);
init.add_docstring("Set up name variable for the Greeter");
init.add_statement(
Statement::Assignment(
Assignment::new(
Argument::variable("self.name"), Statement::variable("name"))));
class.add_statement(Statement::Function(init));
let arguments = vec![
Argument::new("self", None, None, None),
];
let mut hello = Function::new("hello", arguments, &class.block);
hello.add_docstring("Say hello to self.name");
let print = FunctionCall::new("print",
vec![
Statement::unnamed_variable("Hello"),
Statement::variable("self.name"),
Statement::unnamed_variable("!"),
]);
hello.add_statement(Statement::FunctionCall(print));
class.add_statement(Statement::Function(hello));
program.add_statement(Statement::Class(class));
program.add_statement(
Statement::Assignment(Assignment::new(
Argument::variable("g"),
Statement::FunctionCall(FunctionCall::new(
"Greeter",
vec![
Statement::KeywordArgument(KeywordArgument::new("name", "\"Chris\""))
]
))
)));
let function_call = FunctionCall::new("g.hello", vec![]);
program.add_statement(Statement::FunctionCall(function_call));
let expected = r#"class Greeter(Exception):
"""
Greeter is a class to say Hello!
"""
def __init__(self, name="World"):
"""
Set up name variable for the Greeter
:param name: The name to greet
:type name: str
"""
self.name = name
def hello(self):
"""
Say hello to self.name
"""
print("Hello", self.name, "!")
g = Greeter(name="Chris")
g.hello()
"#;
let actual = format!("{}", program);
println!("expected:");
println!("\"{}\"", expected);
println!("actual:");
println!("\"{}\"", actual);
assert_eq!(expected, actual);
}
}
#[derive(Debug, Clone)]
pub struct Class {
pub docstring: Option<Comment>,
pub name: String,
pub block: Block,
pub inherit_from: Option<String>,
}
impl Class {
pub fn new<T: Display>(name: T, parent: &Block) -> Class {
Class {
docstring: None,
name: name.to_string(),
block: Block::new_with_parent(parent),
inherit_from: None,
}
}
pub fn inherit_from<T: Display>(&mut self, inherit: T) {
self.inherit_from = Some(inherit.to_string());
}
pub fn add_statement(&mut self, statement: Statement) {
self.block.add_statement(statement);
}
pub fn add_docstring<T: Display>(&mut self, doc: T) {
self.docstring = Some(Comment::docstring(doc))
}
}
impl Display for Class {
fn fmt(&self, f: &mut Formatter) -> Result {
try!(write!(f, "class {}", self.name));
if let Some(ref inherit) = self.inherit_from {
try!(write!(f, "({})", inherit));
}
try!(write!(f, ":\n"));
let indent: String = self.block.indentation();
if let Some(ref docstring) = self.docstring {
let mut s = String::new();
s.push_str(&format!(r#"{}"""
{}{}
{}"""
"#,
indent,
indent,
docstring,
indent)[..]);
try!(write!(f, "{}", s));
}
write!(f, "{}", self.block)
}
}