123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- use std::fmt;
- pub type Name = string_interner::DefaultSymbol;
- pub struct ASTArena {
- strings: string_interner::StringInterner,
- exprs: Vec<Expr>,
- }
- impl Default for ASTArena {
- fn default() -> Self {
- Self::new()
- }
- }
- impl ASTArena {
- pub fn new() -> ASTArena {
- ASTArena {
- strings: string_interner::StringInterner::new(),
- exprs: vec![Expr::Nil],
- }
- }
- pub fn expr_nil(&self) -> ExprRef {
- ExprRef { idx: 0 }
- }
- pub fn add_expr(&mut self, e: Expr) -> ExprRef {
- let idx = self.exprs.len();
- self.exprs.push(e);
- ExprRef { idx }
- }
- pub fn add_string(&mut self, s: &str) -> Name {
- self.strings.get_or_intern(s)
- }
- pub fn show_stmt(&self, stmt: &Stmt, f: &mut fmt::Formatter) -> fmt::Result {
- match stmt {
- Stmt::Puts(expr) => {
- write!(f, "Puts ")?;
- self.show_expr(&self[*expr], f, 0)
- }
- Stmt::Fix(name) => writeln!(f, "Fix {}", &self[*name]),
- Stmt::Assn(fixed, name, expr) => {
- write!(
- f,
- "Assn {} {} ",
- if *fixed { "fixed" } else { "" },
- &self[*name]
- )?;
- self.show_expr(&self[*expr], f, 0)
- }
- Stmt::LitAssn(fixed, name, strs) => {
- write!(
- f,
- "LitAssn {} {}, [ ",
- if *fixed { "fixed" } else { "" },
- &self[*name],
- )?;
- for str in strs.iter() {
- write!(f, " {} ", str)?;
- }
- writeln!(f, "]")
- }
- }
- }
- fn indent(&self, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
- for _ in 0..depth {
- write!(f, " ")?;
- }
- Ok(())
- }
- fn show_pat(&self, pat: &Pat, f: &mut fmt::Formatter) -> fmt::Result {
- match pat {
- Pat::Wildcard => write!(f, "_"),
- Pat::Var(n) => write!(f, "{}", &self[*n]),
- Pat::Lit(Literal::Atom(n)) => write!(f, "{}", &self[*n]),
- Pat::Lit(lit) => write!(f, "{:?}", lit),
- Pat::Tup(tup) => {
- write!(f, "Tup( ")?;
- for t in tup {
- self.show_pat(t, f)?;
- write!(f, " ")?;
- }
- write!(f, ")")
- }
- }
- }
- fn show_expr(&self, expr: &Expr, f: &mut fmt::Formatter, depth: usize) -> fmt::Result {
- match expr {
- Expr::Nil => writeln!(f, "Nil"),
- Expr::Var(v) => writeln!(f, "Var({})", &self[*v]),
- Expr::Lit(Literal::Atom(n)) => writeln!(f, "Lit(Atom({}))", &self[*n]),
- Expr::Lit(lit) => writeln!(f, "{:?}", lit),
- Expr::Range(from, to) => {
- writeln!(f, "Range(")?;
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*from], f, depth + 2)?;
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*to], f, depth + 2)?;
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- Expr::Ap(func, arg) => {
- writeln!(f, "Ap(")?;
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*func], f, depth + 2)?;
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*arg], f, depth + 2)?;
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- Expr::Tup(expr) => {
- writeln!(f, "Tup(")?;
- for e in expr {
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*e], f, depth + 2)?;
- }
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- Expr::Cat(expr) => {
- writeln!(f, "Cat(")?;
- for e in expr {
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*e], f, depth + 2)?;
- }
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- Expr::Chc(expr) => {
- writeln!(f, "Chc(")?;
- for e in expr {
- if let Some(s) = e.weight {
- self.indent(f, depth + 2)?;
- writeln!(f, "{}:", s)?;
- self.indent(f, depth + 4)?;
- self.show_expr(&self[e.value], f, depth + 4)?;
- } else {
- self.indent(f, depth + 2)?;
- self.show_expr(&self[e.value], f, depth + 2)?;
- }
- }
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- Expr::Let(fixed, name, expr, body) => {
- writeln!(
- f,
- "Let({}{}",
- if *fixed { "fixed " } else { "" },
- &self[*name]
- )?;
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*expr], f, depth + 2)?;
- self.indent(f, depth + 2)?;
- self.show_expr(&self[*body], f, depth + 2)?;
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- Expr::Fun(cases) => {
- writeln!(f, "Fun(")?;
- for case in cases {
- self.indent(f, depth + 2)?;
- self.show_pat(&case.pat, f)?;
- writeln!(f, " =>")?;
- self.indent(f, depth + 4)?;
- self.show_expr(&self[case.expr], f, depth + 4)?;
- }
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- Expr::Case(expr, cases) => {
- writeln!(f, "Case(")?;
- self.indent(f, depth)?;
- self.show_expr(&self[*expr], f, depth)?;
- for case in cases {
- self.indent(f, depth + 2)?;
- self.show_pat(&case.pat, f)?;
- writeln!(f, " =>")?;
- self.indent(f, depth + 4)?;
- self.show_expr(&self[case.expr], f, depth + 4)?;
- }
- self.indent(f, depth)?;
- writeln!(f, ")")
- }
- }
- }
- }
- impl std::ops::Index<string_interner::DefaultSymbol> for ASTArena {
- type Output = str;
- fn index(&self, sf: string_interner::DefaultSymbol) -> &str {
- self.strings.resolve(sf).unwrap()
- }
- }
- impl std::ops::Index<ExprRef> for ASTArena {
- type Output = Expr;
- fn index(&self, rf: ExprRef) -> &Self::Output {
- &self.exprs[rf.idx]
- }
- }
- /// A `Printable` struct is a bundle of another value and an
- /// `ASTArena`, which allows us to fetch the various indices and
- /// dereference the interned strings.
- pub struct Printable<'a, T> {
- arena: &'a ASTArena,
- value: &'a T,
- }
- impl<'a> std::fmt::Debug for Printable<'a, Stmt> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.arena.show_stmt(self.value, f)
- }
- }
- impl<'a> std::fmt::Debug for Printable<'a, Expr> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.arena.show_expr(self.value, f, 0)
- }
- }
- /// A top-level Matzo statement
- #[derive(Debug, Clone, PartialEq, Eq)]
- pub enum Stmt {
- /// evaluate and print the value of an expression
- Puts(ExprRef),
- /// replace a named item with the forced version of that item
- Fix(Name),
- /// assign a value to a name which may or may not be forced
- Assn(bool, Name, ExprRef),
- /// assign one of a set of strings to a name, which may or may not
- /// be forced
- LitAssn(bool, Name, Vec<String>),
- }
- impl Stmt {
- pub fn show<'a>(&'a self, ast: &'a ASTArena) -> Printable<'a, Stmt> {
- Printable {
- arena: ast,
- value: self,
- }
- }
- }
- /// A Matzo expression
- #[derive(Debug, Clone, PartialEq, Eq)]
- pub enum Expr {
- Var(Name),
- Cat(Vec<ExprRef>),
- Chc(Vec<Choice>),
- Lit(Literal),
- Ap(ExprRef, ExprRef),
- Tup(Vec<ExprRef>),
- Let(bool, Name, ExprRef, ExprRef),
- Fun(Vec<Case>),
- Range(ExprRef, ExprRef),
- Case(ExprRef, Vec<Case>),
- Nil,
- }
- #[derive(Debug, Copy, Clone, PartialEq, Eq)]
- pub struct ExprRef {
- idx: usize,
- }
- /// A single case in an anonymous function or `case` statement
- #[derive(Debug, Clone, PartialEq, Eq)]
- pub struct Case {
- pub pat: Pat,
- pub expr: ExprRef,
- }
- /// A pattern, e.g. in an anonymous function or `case` statement
- #[derive(Debug, Clone, PartialEq, Eq)]
- pub enum Pat {
- Var(Name),
- Wildcard,
- Lit(Literal),
- Tup(Vec<Pat>),
- }
- /// A single element in a choice, with an optional weight (which
- /// defaults to 1) and a value
- #[derive(Debug, Clone, PartialEq, Eq)]
- pub struct Choice {
- pub weight: Option<i64>,
- pub value: ExprRef,
- }
- impl Choice {
- /// Fetch a weight from a `Choice`, defaulting to 1
- pub fn weight(&self) -> i64 {
- self.weight.unwrap_or(1)
- }
- }
- /// An atomic literal: a string, a number, or an atom
- #[derive(Debug, Clone, PartialEq, Eq)]
- pub enum Literal {
- Str(String),
- Atom(Name),
- Num(i64),
- }
|