📜 Add better documentation across the compiler. #3
@@ -13,6 +13,16 @@ use proptest::{
|
||||
type Variable = ArcIntern<String>;
|
||||
|
||||
/// The representation of a program within our IR. For now, this is exactly one file.
|
||||
///
|
||||
/// In addition, for the moment there's not really much of interest to hold here besides
|
||||
/// the list of statements read from the file. Order is important. In the future, you
|
||||
/// could imagine caching analysis information in this structure.
|
||||
///
|
||||
/// `Program` implements both [`Pretty`] and [`Arbitrary`]. The former should be used
|
||||
/// to print the structure whenever possible, especially if you value your or your
|
||||
/// user's time. The latter is useful for testing that conversions of `Program` retain
|
||||
/// their meaning. All `Program`s generated through [`Arbitrary`] are guaranteed to be
|
||||
/// syntactically valid, although they may contain runtime issue like over- or underflow.
|
||||
#[derive(Debug)]
|
||||
pub struct Program {
|
||||
// For now, a program is just a vector of statements. In the future, we'll probably
|
||||
@@ -56,6 +66,12 @@ impl Arbitrary for Program {
|
||||
///
|
||||
/// For now, this is either a binding site (`x = 4`) or a print statement
|
||||
/// (`print x`). Someday, though, more!
|
||||
///
|
||||
/// As with `Program`, this type implements [`Pretty`], which should
|
||||
/// be used to display the structure whenever possible. It does not
|
||||
/// implement [`Arbitrary`], though, mostly because it's slightly
|
||||
/// complicated to do so.
|
||||
///
|
||||
#[derive(Debug)]
|
||||
pub enum Statement {
|
||||
Binding(Location, Variable, Expression),
|
||||
@@ -84,6 +100,17 @@ where
|
||||
}
|
||||
|
||||
/// The representation of an expression.
|
||||
///
|
||||
/// Note that expressions, like everything else in this syntax tree,
|
||||
/// supports [`Pretty`], and it's strongly encouraged that you use
|
||||
/// that trait/module when printing these structures.
|
||||
///
|
||||
/// Also, Expressions at this point in the compiler are explicitly
|
||||
/// defined so that they are *not* recursive. By this point, if an
|
||||
/// expression requires some other data (like, for example, invoking
|
||||
/// a primitive), any subexpressions have been bound to variables so
|
||||
/// that the referenced data will always either be a constant or a
|
||||
/// variable reference.
|
||||
#[derive(Debug)]
|
||||
pub enum Expression {
|
||||
Value(Location, Value),
|
||||
@@ -120,6 +147,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A type representing the primitives allowed in the language.
|
||||
///
|
||||
/// Having this as an enumeration avoids a lot of "this should not happen"
|
||||
/// cases, but might prove to be cumbersome in the future. If that happens,
|
||||
/// this may either become a more hierarchical enumeration, or we'll just
|
||||
/// deal with the "this should not happen" cases.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Primitive {
|
||||
Plus,
|
||||
@@ -157,6 +190,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// An expression that is always either a value or a reference.
|
||||
///
|
||||
/// This is the type used to guarantee that we don't nest expressions
|
||||
/// at this level. Instead, expressions that take arguments take one
|
||||
/// of these, which can only be a constant or a reference.
|
||||
#[derive(Debug)]
|
||||
pub enum ValueOrRef {
|
||||
Value(Location, Value),
|
||||
@@ -185,8 +223,14 @@ impl From<ValueOrRef> for Expression {
|
||||
}
|
||||
}
|
||||
|
||||
/// A constant in the IR.
|
||||
#[derive(Debug)]
|
||||
pub enum Value {
|
||||
/// A numerical constant.
|
||||
///
|
||||
/// The optional argument is the base that was used by the user to input
|
||||
/// the number. By retaining it, we can ensure that if we need to print the
|
||||
/// number back out, we can do so in the form that the user entered it.
|
||||
Number(Option<u8>, i64),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user