📜 Add better documentation across the compiler. (#3)
These changes pay particular attention to API endpoints, to try to ensure that any rustdocs generated are detailed and sensible. A good next step, eventually, might be to include doctest examples, as well. For the moment, it's not clear that they would provide a lot of value, though. In addition, this does a couple refactors to simplify the code base in ways that make things clearer or, at least, briefer.
This commit is contained in:
@@ -4,11 +4,23 @@ use crate::eval::{EvalEnvironment, EvalError, Value};
|
||||
use crate::syntax::{Expression, Program, Statement};
|
||||
|
||||
impl Program {
|
||||
/// Evaluate the program, returning either an error or what it prints out when run.
|
||||
///
|
||||
/// Doing this evaluation is particularly useful for testing, to ensure that if we
|
||||
/// modify a program in some way it does the same thing on both sides of the
|
||||
/// transformation. It's also sometimes just nice to know what a program will be
|
||||
/// doing.
|
||||
///
|
||||
/// Note that the errors here are slightly more strict that we enforce at runtime.
|
||||
/// For example, we check for overflow and underflow errors during evaluation, and
|
||||
/// we don't check for those in the compiled code.
|
||||
pub fn eval(&self) -> Result<String, EvalError> {
|
||||
let mut env = EvalEnvironment::empty();
|
||||
let mut stdout = String::new();
|
||||
|
||||
for stmt in self.statements.iter() {
|
||||
// at this point, evaluation is pretty simple. just walk through each
|
||||
// statement, in order, and record printouts as we come to them.
|
||||
match stmt {
|
||||
Statement::Binding(_, name, value) => {
|
||||
let actual_value = value.eval(&env)?;
|
||||
@@ -40,6 +52,7 @@ impl Expression {
|
||||
let mut arg_values = Vec::with_capacity(args.len());
|
||||
|
||||
for arg in args.iter() {
|
||||
// yay, recursion! makes this pretty straightforward
|
||||
arg_values.push(arg.eval(env)?);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user