📜 Add better documentation across the compiler. #3
@@ -13,6 +13,16 @@ use proptest::{
|
|||||||
type Variable = ArcIntern<String>;
|
type Variable = ArcIntern<String>;
|
||||||
|
|
||||||
/// The representation of a program within our IR. For now, this is exactly one file.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
pub struct Program {
|
pub struct Program {
|
||||||
// For now, a program is just a vector of statements. In the future, we'll probably
|
// 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
|
/// For now, this is either a binding site (`x = 4`) or a print statement
|
||||||
/// (`print x`). Someday, though, more!
|
/// (`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)]
|
#[derive(Debug)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
Binding(Location, Variable, Expression),
|
Binding(Location, Variable, Expression),
|
||||||
@@ -84,6 +100,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The representation of an expression.
|
/// 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)]
|
#[derive(Debug)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Value(Location, Value),
|
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)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum Primitive {
|
pub enum Primitive {
|
||||||
Plus,
|
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)]
|
#[derive(Debug)]
|
||||||
pub enum ValueOrRef {
|
pub enum ValueOrRef {
|
||||||
Value(Location, Value),
|
Value(Location, Value),
|
||||||
@@ -185,8 +223,14 @@ impl From<ValueOrRef> for Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A constant in the IR.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Value {
|
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),
|
Number(Option<u8>, i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user