//! Semantic analysis.
//!
//! This module primarily contains the type environment and term environment.
//!
//! The type environment is constructed by analyzing an input AST. The type
//! environment records the types used in the input source and the types of our
//! various rules and symbols. ISLE's type system is intentionally easy to
//! check, only requires a single pass over the AST, and doesn't require any
//! unification or anything like that.
//!
//! The term environment is constructed from both the AST and type
//! environment. It is sort of a typed and reorganized AST that more directly
//! reflects ISLE semantics than the input ISLE source code (where as the AST is
//! the opposite).

use crate::ast;
use crate::error::*;
use crate::lexer::Pos;
use crate::log;
use crate::stablemapset::{StableMap, StableSet};
use std::collections::hash_map::Entry;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::collections::HashMap;
use std::sync::Arc;

declare_id!(
    /// The id of an interned symbol.
    Sym
);
declare_id!(
    /// The id of an interned type inside the `TypeEnv`.
    TypeId
);
declare_id!(
    /// The id of a variant inside an enum.
    VariantId
);
declare_id!(
    /// The id of a field inside a variant.
    FieldId
);
declare_id!(
    /// The id of an interned term inside the `TermEnv`.
    TermId
);
declare_id!(
    /// The id of an interned rule inside the `TermEnv`.
    RuleId
);
declare_id!(
    /// The id of a bound variable inside a `Bindings`.
    VarId
);

/// The type environment.
///
/// Keeps track of which symbols and rules have which types.
#[derive(Debug)]
pub struct TypeEnv {
    /// Arena of input ISLE source filenames.
    ///
    /// We refer to these indirectly through the `Pos::file` indices.
    pub filenames: Vec<Arc<str>>,

    /// Arena of input ISLE source contents.
    ///
    /// We refer to these indirectly through the `Pos::file` indices.
    pub file_texts: Vec<Arc<str>>,

    /// Arena of interned symbol names.
    ///
    /// Referred to indirectly via `Sym` indices.
    pub syms: Vec<String>,

    /// Map of already-interned symbol names to their `Sym` ids.
    pub sym_map: StableMap<String, Sym>,

    /// Arena of type definitions.
    ///
    /// Referred to indirectly via `TypeId`s.
    pub types: Vec<Type>,

    /// A map from a type name symbol to its `TypeId`.
    pub type_map: StableMap<Sym, TypeId>,

    /// The types of constant symbols.
    pub const_types: StableMap<Sym, TypeId>,

    /// Type errors that we've found so far during type checking.
    pub errors: Vec<Error>,
}

/// A type.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Type {
    /// A primitive, `Copy` type.
    ///
    /// These are always defined externally, and we allow literals of these
    /// types to pass through from ISLE source code to the emitted Rust code.
    Primitive(TypeId, Sym, Pos),

    /// A sum type.
    ///
    /// Note that enums with only one variant are equivalent to a "struct".
    Enum {
        /// The name of this enum.
        name: Sym,
        /// This `enum`'s type id.
        id: TypeId,
        /// Is this `enum` defined in external Rust code?
        ///
        /// If so, ISLE will not emit a definition for it. If not, then it will
        /// emit a Rust definition for it.
        is_extern: bool,
        /// Whether this type should *not* derive `Debug`.
        ///
        /// Incompatible with `is_extern`.
        is_nodebug: bool,
        /// The different variants for this enum.
        variants: Vec<Variant>,
        /// The ISLE source position where this `enum` is defined.
        pos: Pos,
    },
}

impl Type {
    /// Get the name of this `Type`.
    pub fn name<'a>(&self, tyenv: &'a TypeEnv) -> &'a str {
        match self {
            Self::Primitive(_, name, _) | Self::Enum { name, .. } => &tyenv.syms[name.index()],
        }
    }

    /// Get the position where this type was defined.
    pub fn pos(&self) -> Pos {
        match self {
            Self::Primitive(_, _, pos) | Self::Enum { pos, .. } => *pos,
        }
    }

    /// Is this a primitive type?
    pub fn is_prim(&self) -> bool {
        matches!(self, Type::Primitive(..))
    }
}

/// A variant of an enum.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Variant {
    /// The name of this variant.
    pub name: Sym,

    /// The full, prefixed-with-the-enum's-name name of this variant.
    ///
    /// E.g. if the enum is `Foo` and this variant is `Bar`, then the
    /// `fullname` is `Foo.Bar`.
    pub fullname: Sym,

    /// The id of this variant, i.e. the index of this variant within its
    /// enum's `Type::Enum::variants`.
    pub id: VariantId,

    /// The data fields of this enum variant.
    pub fields: Vec<Field>,
}

/// A field of a `Variant`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Field {
    /// The name of this field.
    pub name: Sym,
    /// This field's id.
    pub id: FieldId,
    /// The type of this field.
    pub ty: TypeId,
}

/// The term environment.
///
/// This is sort of a typed and reorganized AST that more directly reflects ISLE
/// semantics than the input ISLE source code (where as the AST is the
/// opposite).
#[derive(Clone, Debug)]
pub struct TermEnv {
    /// Arena of interned terms defined in this ISLE program.
    ///
    /// This is indexed by `TermId`.
    pub terms: Vec<Term>,

    /// A map from am interned `Term`'s name to its `TermId`.
    pub term_map: StableMap<Sym, TermId>,

    /// Arena of interned rules defined in this ISLE program.
    ///
    /// This is indexed by `RuleId`.
    pub rules: Vec<Rule>,

    /// Map from (inner_ty, outer_ty) pairs to term IDs, giving the
    /// defined implicit type-converter terms we can try to use to fit
    /// types together.
    pub converters: StableMap<(TypeId, TypeId), TermId>,
}

/// A term.
///
/// Maps parameter types to result types if this is a constructor term, or
/// result types to parameter types if this is an extractor term. Or both if
/// this term can be either a constructor or an extractor.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Term {
    /// This term's id.
    pub id: TermId,
    /// The source position where this term was declared.
    pub decl_pos: Pos,
    /// The name of this term.
    pub name: Sym,
    /// The parameter types to this term.
    pub arg_tys: Vec<TypeId>,
    /// The result types of this term.
    pub ret_ty: TypeId,
    /// The kind of this term.
    pub kind: TermKind,
}

/// Flags from a term's declaration with `(decl ...)`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TermFlags {
    /// Whether the term is marked as `pure`.
    pub pure: bool,
    /// Whether the term is marked as `multi`.
    pub multi: bool,
    /// Whether the term is marked as `partial`.
    pub partial: bool,
}

/// The kind of a term.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TermKind {
    /// An enum variant constructor or extractor.
    EnumVariant {
        /// Which variant of the enum: e.g. for enum type `A` if a term is
        /// `(A.A1 ...)` then the variant ID corresponds to `A1`.
        variant: VariantId,
    },
    /// A term declared via a `(decl ...)` form.
    Decl {
        /// Flags from the term's declaration.
        flags: TermFlags,
        /// The kind of this term's constructor, if any.
        constructor_kind: Option<ConstructorKind>,
        /// The kind of this term's extractor, if any.
        extractor_kind: Option<ExtractorKind>,
    },
}

/// The kind of a constructor for a term.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConstructorKind {
    /// A term with "internal" rules that work in the forward direction. Becomes
    /// a compiled Rust function in the generated code.
    InternalConstructor,
    /// A term defined solely by an external constructor function.
    ExternalConstructor {
        /// The external name of the constructor function.
        name: Sym,
    },
}

/// The kind of an extractor for a term.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ExtractorKind {
    /// A term that defines an "extractor macro" in the LHS of a pattern. Its
    /// arguments take patterns and are simply substituted with the given
    /// patterns when used.
    InternalExtractor {
        /// This extractor's pattern.
        template: ast::Pattern,
    },
    /// A term defined solely by an external extractor function.
    ExternalExtractor {
        /// The external name of the extractor function.
        name: Sym,
        /// Is the external extractor infallible?
        infallible: bool,
        /// The position where this external extractor was declared.
        pos: Pos,
    },
}

/// How many values a function can return.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ReturnKind {
    /// Exactly one return value.
    Plain,
    /// Zero or one return values.
    Option,
    /// Zero or more return values.
    Iterator,
}

/// An external function signature.
#[derive(Clone, Debug)]
pub struct ExternalSig {
    /// The name of the external function.
    pub func_name: String,
    /// The name of the external function, prefixed with the context trait.
    pub full_name: String,
    /// The types of this function signature's parameters.
    pub param_tys: Vec<TypeId>,
    /// The types of this function signature's results.
    pub ret_tys: Vec<TypeId>,
    /// How many values can this function return?
    pub ret_kind: ReturnKind,
}

impl Term {
    /// Get this term's type.
    pub fn ty(&self) -> TypeId {
        self.ret_ty
    }

    fn check_args_count<T>(&self, args: &[T], tyenv: &mut TypeEnv, pos: Pos, sym: &ast::Ident) {
        if self.arg_tys.len() != args.len() {
            tyenv.report_error(
                pos,
                format!(
                    "Incorrect argument count for term '{}': got {}, expect {}",
                    sym.0,
                    args.len(),
                    self.arg_tys.len()
                ),
            );
        }
    }

    /// Is this term an enum variant?
    pub fn is_enum_variant(&self) -> bool {
        matches!(self.kind, TermKind::EnumVariant { .. })
    }

    /// Is this term partial?
    pub fn is_partial(&self) -> bool {
        matches!(
            self.kind,
            TermKind::Decl {
                flags: TermFlags { partial: true, .. },
                ..
            }
        )
    }

    /// Does this term have a constructor?
    pub fn has_constructor(&self) -> bool {
        matches!(
            self.kind,
            TermKind::EnumVariant { .. }
                | TermKind::Decl {
                    constructor_kind: Some(_),
                    ..
                }
        )
    }

    /// Does this term have an extractor?
    pub fn has_extractor(&self) -> bool {
        matches!(
            self.kind,
            TermKind::EnumVariant { .. }
                | TermKind::Decl {
                    extractor_kind: Some(_),
                    ..
                }
        )
    }

    /// Is this term's extractor external?
    pub fn has_external_extractor(&self) -> bool {
        matches!(
            self.kind,
            TermKind::Decl {
                extractor_kind: Some(ExtractorKind::ExternalExtractor { .. }),
                ..
            }
        )
    }

    /// Is this term's constructor external?
    pub fn has_external_constructor(&self) -> bool {
        matches!(
            self.kind,
            TermKind::Decl {
                constructor_kind: Some(ConstructorKind::ExternalConstructor { .. }),
                ..
            }
        )
    }

    /// Get this term's extractor's external function signature, if any.
    pub fn extractor_sig(&self, tyenv: &TypeEnv) -> Option<ExternalSig> {
        match &self.kind {
            TermKind::Decl {
                flags,
                extractor_kind:
                    Some(ExtractorKind::ExternalExtractor {
                        name, infallible, ..
                    }),
                ..
            } => {
                let ret_kind = if flags.multi {
                    ReturnKind::Iterator
                } else if *infallible {
                    ReturnKind::Plain
                } else {
                    ReturnKind::Option
                };
                Some(ExternalSig {
                    func_name: tyenv.syms[name.index()].clone(),
                    full_name: format!("C::{}", tyenv.syms[name.index()]),
                    param_tys: vec![self.ret_ty],
                    ret_tys: self.arg_tys.clone(),
                    ret_kind,
                })
            }
            _ => None,
        }
    }

    /// Get this term's constructor's external function signature, if any.
    pub fn constructor_sig(&self, tyenv: &TypeEnv) -> Option<ExternalSig> {
        match &self.kind {
            TermKind::Decl {
                constructor_kind: Some(kind),
                flags,
                ..
            } => {
                let (func_name, full_name) = match kind {
                    ConstructorKind::InternalConstructor => {
                        let name = format!("constructor_{}", tyenv.syms[self.name.index()]);
                        (name.clone(), name)
                    }
                    ConstructorKind::ExternalConstructor { name } => (
                        tyenv.syms[name.index()].clone(),
                        format!("C::{}", tyenv.syms[name.index()]),
                    ),
                };
                let ret_kind = if flags.multi {
                    ReturnKind::Iterator
                } else if flags.partial {
                    ReturnKind::Option
                } else {
                    ReturnKind::Plain
                };
                Some(ExternalSig {
                    func_name,
                    full_name,
                    param_tys: self.arg_tys.clone(),
                    ret_tys: vec![self.ret_ty],
                    ret_kind,
                })
            }
            _ => None,
        }
    }
}

/// A term rewrite rule.
#[derive(Clone, Debug)]
pub struct Rule {
    /// This rule's id.
    pub id: RuleId,
    /// The left-hand side pattern that this rule matches.
    pub root_term: TermId,
    /// Patterns to test against the root term's arguments.
    pub args: Vec<Pattern>,
    /// Any subpattern "if-let" clauses.
    pub iflets: Vec<IfLet>,
    /// The right-hand side expression that this rule evaluates upon successful
    /// match.
    pub rhs: Expr,
    /// Variable names used in this rule, indexed by [VarId].
    pub vars: Vec<BoundVar>,
    /// The priority of this rule, defaulted to 0 if it was missing in the source.
    pub prio: i64,
    /// The source position where this rule is defined.
    pub pos: Pos,
}

/// A name bound in a pattern or let-expression.
#[derive(Clone, Debug)]
pub struct BoundVar {
    /// The identifier used for this variable within the scope of the current [Rule].
    pub id: VarId,
    /// The variable's name.
    pub name: Sym,
    /// The type of the value this variable is bound to.
    pub ty: TypeId,
    /// A counter used to check whether this variable is still in scope during
    /// semantic analysis. Not meaningful afterward.
    scope: usize,
}

/// An `if-let` clause with a subpattern match on an expr after the
/// main LHS matches.
#[derive(Clone, Debug)]
pub struct IfLet {
    /// The left-hand side pattern that this `if-let` clause matches
    /// against the expression below.
    pub lhs: Pattern,
    /// The right-hand side expression that this pattern
    /// evaluates. Must be pure.
    pub rhs: Expr,
}

/// A left-hand side pattern of some rule.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Pattern {
    /// Bind a variable of the given type from the current value.
    ///
    /// Keep matching on the value with the subpattern.
    BindPattern(TypeId, VarId, Box<Pattern>),

    /// Match the current value against an already bound variable with the given
    /// type.
    Var(TypeId, VarId),

    /// Match the current value against a constant integer of the given integer
    /// type.
    ConstInt(TypeId, i128),

    /// Match the current value against a constant primitive value of the given
    /// primitive type.
    ConstPrim(TypeId, Sym),

    /// Match the current value against the given extractor term with the given
    /// arguments.
    Term(TypeId, TermId, Vec<Pattern>),

    /// Match anything of the given type successfully.
    Wildcard(TypeId),

    /// Match all of the following patterns of the given type.
    And(TypeId, Vec<Pattern>),
}

/// A right-hand side expression of some rule.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
    /// Invoke this term constructor with the given arguments.
    Term(TypeId, TermId, Vec<Expr>),
    /// Get the value of a variable that was bound in the left-hand side.
    Var(TypeId, VarId),
    /// Get a constant integer.
    ConstInt(TypeId, i128),
    /// Get a constant primitive.
    ConstPrim(TypeId, Sym),
    /// Evaluate the nested expressions and bind their results to the given
    /// variables, then evaluate the body expression.
    Let {
        /// The type of the result of this let expression.
        ty: TypeId,
        /// The expressions that are evaluated and bound to the given variables.
        bindings: Vec<(VarId, TypeId, Box<Expr>)>,
        /// The body expression that is evaluated after the bindings.
        body: Box<Expr>,
    },
}

/// Visitor interface for [Pattern]s. Visitors can assign an arbitrary identifier to each
/// subpattern, which is threaded through to subsequent calls into the visitor.
pub trait PatternVisitor {
    /// The type of subpattern identifiers.
    type PatternId: Copy;

    /// Match if `a` and `b` have equal values.
    fn add_match_equal(&mut self, a: Self::PatternId, b: Self::PatternId, ty: TypeId);
    /// Match if `input` is the given integer constant.
    fn add_match_int(&mut self, input: Self::PatternId, ty: TypeId, int_val: i128);
    /// Match if `input` is the given primitive constant.
    fn add_match_prim(&mut self, input: Self::PatternId, ty: TypeId, val: Sym);

    /// Match if `input` is the given enum variant. Returns an identifier for each field within the
    /// enum variant. The length of the return list must equal the length of `arg_tys`.
    fn add_match_variant(
        &mut self,
        input: Self::PatternId,
        input_ty: TypeId,
        arg_tys: &[TypeId],
        variant: VariantId,
    ) -> Vec<Self::PatternId>;

    /// Match if the given external extractor succeeds on `input`. Returns an identifier for each
    /// return value from the external extractor. The length of the return list must equal the
    /// length of `output_tys`.
    fn add_extract(
        &mut self,
        input: Self::PatternId,
        input_ty: TypeId,
        output_tys: Vec<TypeId>,
        term: TermId,
        infallible: bool,
        multi: bool,
    ) -> Vec<Self::PatternId>;
}

impl Pattern {
    /// Get this pattern's type.
    pub fn ty(&self) -> TypeId {
        match *self {
            Self::BindPattern(t, ..) => t,
            Self::Var(t, ..) => t,
            Self::ConstInt(t, ..) => t,
            Self::ConstPrim(t, ..) => t,
            Self::Term(t, ..) => t,
            Self::Wildcard(t, ..) => t,
            Self::And(t, ..) => t,
        }
    }

    /// Recursively visit every sub-pattern.
    pub fn visit<V: PatternVisitor>(
        &self,
        visitor: &mut V,
        input: V::PatternId,
        termenv: &TermEnv,
        vars: &mut HashMap<VarId, V::PatternId>,
    ) {
        match *self {
            Pattern::BindPattern(_ty, var, ref subpat) => {
                // Bind the appropriate variable and recurse.
                assert!(!vars.contains_key(&var));
                vars.insert(var, input);
                subpat.visit(visitor, input, termenv, vars);
            }
            Pattern::Var(ty, var) => {
                // Assert that the value matches the existing bound var.
                let var_val = vars
                    .get(&var)
                    .copied()
                    .expect("Variable should already be bound");
                visitor.add_match_equal(input, var_val, ty);
            }
            Pattern::ConstInt(ty, value) => visitor.add_match_int(input, ty, value),
            Pattern::ConstPrim(ty, value) => visitor.add_match_prim(input, ty, value),
            Pattern::Term(ty, term, ref args) => {
                // Determine whether the term has an external extractor or not.
                let termdata = &termenv.terms[term.index()];
                let arg_values = match &termdata.kind {
                    TermKind::EnumVariant { variant } => {
                        visitor.add_match_variant(input, ty, &termdata.arg_tys, *variant)
                    }
                    TermKind::Decl {
                        extractor_kind: None,
                        ..
                    } => {
                        panic!("Pattern invocation of undefined term body")
                    }
                    TermKind::Decl {
                        extractor_kind: Some(ExtractorKind::InternalExtractor { .. }),
                        ..
                    } => {
                        panic!("Should have been expanded away")
                    }
                    TermKind::Decl {
                        flags,
                        extractor_kind: Some(ExtractorKind::ExternalExtractor { infallible, .. }),
                        ..
                    } => {
                        // Evaluate all `input` args.
                        let output_tys = args.iter().map(|arg| arg.ty()).collect();

                        // Invoke the extractor.
                        visitor.add_extract(
                            input,
                            termdata.ret_ty,
                            output_tys,
                            term,
                            *infallible && !flags.multi,
                            flags.multi,
                        )
                    }
                };
                for (pat, val) in args.iter().zip(arg_values) {
                    pat.visit(visitor, val, termenv, vars);
                }
            }
            Pattern::And(_ty, ref children) => {
                for child in children {
                    child.visit(visitor, input, termenv, vars);
                }
            }
            Pattern::Wildcard(_ty) => {
                // Nothing!
            }
        }
    }
}

/// Visitor interface for [Expr]s. Visitors can return an arbitrary identifier for each
/// subexpression, which is threaded through to subsequent calls into the visitor.
pub trait ExprVisitor {
    /// The type of subexpression identifiers.
    type ExprId: Copy;

    /// Construct a constant integer.
    fn add_const_int(&mut self, ty: TypeId, val: i128) -> Self::ExprId;
    /// Construct a primitive constant.
    fn add_const_prim(&mut self, ty: TypeId, val: Sym) -> Self::ExprId;

    /// Construct an enum variant with the given `inputs` assigned to the variant's fields in order.
    fn add_create_variant(
        &mut self,
        inputs: Vec<(Self::ExprId, TypeId)>,
        ty: TypeId,
        variant: VariantId,
    ) -> Self::ExprId;

    /// Call an external constructor with the given `inputs` as arguments.
    fn add_construct(
        &mut self,
        inputs: Vec<(Self::ExprId, TypeId)>,
        ty: TypeId,
        term: TermId,
        pure: bool,
        infallible: bool,
        multi: bool,
    ) -> Self::ExprId;
}

impl Expr {
    /// Get this expression's type.
    pub fn ty(&self) -> TypeId {
        match *self {
            Self::Term(t, ..) => t,
            Self::Var(t, ..) => t,
            Self::ConstInt(t, ..) => t,
            Self::ConstPrim(t, ..) => t,
            Self::Let { ty: t, .. } => t,
        }
    }

    /// Recursively visit every subexpression.
    pub fn visit<V: ExprVisitor>(
        &self,
        visitor: &mut V,
        termenv: &TermEnv,
        vars: &HashMap<VarId, V::ExprId>,
    ) -> V::ExprId {
        log!("Expr::visit: expr {:?}", self);
        match *self {
            Expr::ConstInt(ty, val) => visitor.add_const_int(ty, val),
            Expr::ConstPrim(ty, val) => visitor.add_const_prim(ty, val),
            Expr::Let {
                ty: _ty,
                ref bindings,
                ref body,
            } => {
                let mut vars = vars.clone();
                for &(var, _var_ty, ref var_expr) in bindings {
                    let var_value = var_expr.visit(visitor, termenv, &vars);
                    vars.insert(var, var_value);
                }
                body.visit(visitor, termenv, &vars)
            }
            Expr::Var(_ty, var_id) => *vars.get(&var_id).unwrap(),
            Expr::Term(ty, term, ref arg_exprs) => {
                let termdata = &termenv.terms[term.index()];
                let arg_values_tys = arg_exprs
                    .iter()
                    .map(|arg_expr| arg_expr.visit(visitor, termenv, vars))
                    .zip(termdata.arg_tys.iter().copied())
                    .collect();
                match &termdata.kind {
                    TermKind::EnumVariant { variant } => {
                        visitor.add_create_variant(arg_values_tys, ty, *variant)
                    }
                    TermKind::Decl {
                        constructor_kind: Some(_),
                        flags,
                        ..
                    } => {
                        visitor.add_construct(
                            arg_values_tys,
                            ty,
                            term,
                            flags.pure,
                            /* infallible = */ !flags.partial,
                            flags.multi,
                        )
                    }
                    TermKind::Decl {
                        constructor_kind: None,
                        ..
                    } => panic!("Should have been caught by typechecking"),
                }
            }
        }
    }

    fn visit_in_rule<V: RuleVisitor>(
        &self,
        visitor: &mut V,
        termenv: &TermEnv,
        vars: &HashMap<VarId, <V::PatternVisitor as PatternVisitor>::PatternId>,
    ) -> V::Expr {
        let var_exprs = vars
            .iter()
            .map(|(&var, &val)| (var, visitor.pattern_as_expr(val)))
            .collect();
        visitor.add_expr(|visitor| VisitedExpr {
            ty: self.ty(),
            value: self.visit(visitor, termenv, &var_exprs),
        })
    }
}

/// Information about an expression after it has been fully visited in [RuleVisitor::add_expr].
#[derive(Clone, Copy)]
pub struct VisitedExpr<V: ExprVisitor> {
    /// The type of the top-level expression.
    pub ty: TypeId,
    /// The identifier returned by the visitor for the top-level expression.
    pub value: V::ExprId,
}

/// Visitor interface for [Rule]s. Visitors must be able to visit patterns by implementing
/// [PatternVisitor], and to visit expressions by providing a type that implements [ExprVisitor].
pub trait RuleVisitor {
    /// The type of pattern visitors constructed by [RuleVisitor::add_pattern].
    type PatternVisitor: PatternVisitor;
    /// The type of expression visitors constructed by [RuleVisitor::add_expr].
    type ExprVisitor: ExprVisitor;
    /// The type returned from [RuleVisitor::add_expr], which may be exchanged for a subpattern
    /// identifier using [RuleVisitor::expr_as_pattern].
    type Expr;

    /// Visit one of the arguments to the top-level pattern.
    fn add_arg(
        &mut self,
        index: usize,
        ty: TypeId,
    ) -> <Self::PatternVisitor as PatternVisitor>::PatternId;

    /// Visit a pattern, used once for the rule's left-hand side and once for each if-let. You can
    /// determine which part of the rule the pattern comes from based on whether the `PatternId`
    /// passed to the first call to this visitor came from `add_arg` or `expr_as_pattern`.
    fn add_pattern<F>(&mut self, visitor: F)
    where
        F: FnOnce(&mut Self::PatternVisitor);

    /// Visit an expression, used once for each if-let and once for the rule's right-hand side.
    fn add_expr<F>(&mut self, visitor: F) -> Self::Expr
    where
        F: FnOnce(&mut Self::ExprVisitor) -> VisitedExpr<Self::ExprVisitor>;

    /// Given an expression from [RuleVisitor::add_expr], return an identifier that can be used with
    /// a pattern visitor in [RuleVisitor::add_pattern].
    fn expr_as_pattern(
        &mut self,
        expr: Self::Expr,
    ) -> <Self::PatternVisitor as PatternVisitor>::PatternId;

    /// Given an identifier from the pattern visitor, return an identifier that can be used with
    /// the expression visitor.
    fn pattern_as_expr(
        &mut self,
        pattern: <Self::PatternVisitor as PatternVisitor>::PatternId,
    ) -> <Self::ExprVisitor as ExprVisitor>::ExprId;
}

impl Rule {
    /// Recursively visit every pattern and expression in this rule. Returns the [RuleVisitor::Expr]
    /// that was returned from [RuleVisitor::add_expr] when that function was called on the rule's
    /// right-hand side.
    pub fn visit<V: RuleVisitor>(&self, visitor: &mut V, termenv: &TermEnv) -> V::Expr {
        let mut vars = HashMap::new();

        // Visit the pattern, starting from the root input value.
        let termdata = &termenv.terms[self.root_term.index()];
        for (i, (subpat, &arg_ty)) in self.args.iter().zip(termdata.arg_tys.iter()).enumerate() {
            let value = visitor.add_arg(i, arg_ty);
            visitor.add_pattern(|visitor| subpat.visit(visitor, value, termenv, &mut vars));
        }

        // Visit the `if-let` clauses, using `V::ExprVisitor` for the sub-exprs (right-hand sides).
        for iflet in self.iflets.iter() {
            let subexpr = iflet.rhs.visit_in_rule(visitor, termenv, &vars);
            let value = visitor.expr_as_pattern(subexpr);
            visitor.add_pattern(|visitor| iflet.lhs.visit(visitor, value, termenv, &mut vars));
        }

        // Visit the rule's right-hand side, making use of the bound variables from the pattern.
        self.rhs.visit_in_rule(visitor, termenv, &vars)
    }
}

/// Given an `Option<T>`, unwrap the inner `T` value, or `continue` if it is
/// `None`.
///
/// Useful for when we encountered an error earlier in our analysis but kept
/// going to find more errors, and now we've run into some missing data that
/// would have been filled in if we didn't hit that original error, but we want
/// to keep going to find more errors.
macro_rules! unwrap_or_continue {
    ($e:expr) => {
        match $e {
            Some(x) => x,
            None => continue,
        }
    };
}

impl TypeEnv {
    /// Construct the type environment from the AST.
    pub fn from_ast(defs: &ast::Defs) -> Result<TypeEnv, Errors> {
        let mut tyenv = TypeEnv {
            filenames: defs.filenames.clone(),
            file_texts: defs.file_texts.clone(),
            syms: vec![],
            sym_map: StableMap::new(),
            types: vec![],
            type_map: StableMap::new(),
            const_types: StableMap::new(),
            errors: vec![],
        };

        // Traverse defs, assigning type IDs to type names. We'll fill
        // in types on a second pass.
        for def in &defs.defs {
            match def {
                &ast::Def::Type(ref td) => {
                    let tid = TypeId(tyenv.type_map.len());
                    let name = tyenv.intern_mut(&td.name);

                    if let Some(existing) = tyenv.type_map.get(&name).copied() {
                        tyenv.report_error(
                            td.pos,
                            format!("Type with name '{}' defined more than once", td.name.0),
                        );
                        let pos = unwrap_or_continue!(tyenv.types.get(existing.index())).pos();
                        tyenv.report_error(
                            pos,
                            format!("Type with name '{}' already defined here", td.name.0),
                        );
                        continue;
                    }

                    tyenv.type_map.insert(name, tid);
                }
                _ => {}
            }
        }

        // Now lower AST nodes to type definitions, raising errors
        // where typenames of fields are undefined or field names are
        // duplicated.
        for def in &defs.defs {
            match def {
                &ast::Def::Type(ref td) => {
                    let tid = tyenv.types.len();
                    if let Some(ty) = tyenv.type_from_ast(TypeId(tid), td) {
                        tyenv.types.push(ty);
                    }
                }
                _ => {}
            }
        }

        // Now collect types for extern constants.
        for def in &defs.defs {
            if let &ast::Def::Extern(ast::Extern::Const {
                ref name,
                ref ty,
                pos,
            }) = def
            {
                let ty = match tyenv.get_type_by_name(ty) {
                    Some(ty) => ty,
                    None => {
                        tyenv.report_error(pos, "Unknown type for constant");
                        continue;
                    }
                };
                let name = tyenv.intern_mut(name);
                tyenv.const_types.insert(name, ty);
            }
        }

        tyenv.return_errors()?;

        Ok(tyenv)
    }

    fn return_errors(&mut self) -> Result<(), Errors> {
        if self.errors.is_empty() {
            Ok(())
        } else {
            Err(Errors {
                errors: std::mem::take(&mut self.errors),
                filenames: self.filenames.clone(),
                file_texts: self.file_texts.clone(),
            })
        }
    }

    fn type_from_ast(&mut self, tid: TypeId, ty: &ast::Type) -> Option<Type> {
        let name = self.intern(&ty.name).unwrap();
        match &ty.ty {
            &ast::TypeValue::Primitive(ref id, ..) => {
                if ty.is_nodebug {
                    self.report_error(ty.pos, "primitive types cannot be marked `nodebug`");
                    return None;
                }
                if ty.is_extern {
                    self.report_error(ty.pos, "primitive types cannot be marked `extern`");
                    return None;
                }
                Some(Type::Primitive(tid, self.intern_mut(id), ty.pos))
            }
            &ast::TypeValue::Enum(ref ty_variants, ..) => {
                if ty.is_extern && ty.is_nodebug {
                    self.report_error(ty.pos, "external types cannot be marked `nodebug`");
                    return None;
                }

                let mut variants = vec![];
                for variant in ty_variants {
                    let combined_ident =
                        ast::Ident(format!("{}.{}", ty.name.0, variant.name.0), variant.name.1);
                    let fullname = self.intern_mut(&combined_ident);
                    let name = self.intern_mut(&variant.name);
                    let id = VariantId(variants.len());
                    if variants.iter().any(|v: &Variant| v.name == name) {
                        self.report_error(
                            variant.pos,
                            format!("Duplicate variant name in type: '{}'", variant.name.0),
                        );
                        return None;
                    }
                    let mut fields = vec![];
                    for field in &variant.fields {
                        let field_name = self.intern_mut(&field.name);
                        if fields.iter().any(|f: &Field| f.name == field_name) {
                            self.report_error(
                                field.pos,
                                format!(
                                    "Duplicate field name '{}' in variant '{}' of type",
                                    field.name.0, variant.name.0
                                ),
                            );
                            return None;
                        }
                        let field_tid = match self.get_type_by_name(&field.ty) {
                            Some(tid) => tid,
                            None => {
                                self.report_error(
                                    field.ty.1,
                                    format!(
                                        "Unknown type '{}' for field '{}' in variant '{}'",
                                        field.ty.0, field.name.0, variant.name.0
                                    ),
                                );
                                return None;
                            }
                        };
                        fields.push(Field {
                            name: field_name,
                            id: FieldId(fields.len()),
                            ty: field_tid,
                        });
                    }
                    variants.push(Variant {
                        name,
                        fullname,
                        id,
                        fields,
                    });
                }
                Some(Type::Enum {
                    name,
                    id: tid,
                    is_extern: ty.is_extern,
                    is_nodebug: ty.is_nodebug,
                    variants,
                    pos: ty.pos,
                })
            }
        }
    }

    fn error(&self, pos: Pos, msg: impl Into<String>) -> Error {
        Error::TypeError {
            msg: msg.into(),
            span: Span::new_single(pos),
        }
    }

    fn report_error(&mut self, pos: Pos, msg: impl Into<String>) {
        let err = self.error(pos, msg);
        self.errors.push(err);
    }

    fn intern_mut(&mut self, ident: &ast::Ident) -> Sym {
        if let Some(s) = self.sym_map.get(&ident.0).copied() {
            s
        } else {
            let s = Sym(self.syms.len());
            self.syms.push(ident.0.clone());
            self.sym_map.insert(ident.0.clone(), s);
            s
        }
    }

    fn intern(&self, ident: &ast::Ident) -> Option<Sym> {
        self.sym_map.get(&ident.0).copied()
    }

    fn get_type_by_name(&self, sym: &ast::Ident) -> Option<TypeId> {
        self.intern(sym)
            .and_then(|sym| self.type_map.get(&sym))
            .copied()
    }
}

#[derive(Clone, Debug, Default)]
struct Bindings {
    /// All bindings accumulated so far within the current rule, including let-
    /// bindings which have gone out of scope.
    seen: Vec<BoundVar>,
    /// Counter for unique scope IDs within this set of bindings.
    next_scope: usize,
    /// Stack of the scope IDs for bindings which are currently in scope.
    in_scope: Vec<usize>,
}

impl Bindings {
    fn enter_scope(&mut self) {
        self.in_scope.push(self.next_scope);
        self.next_scope += 1;
    }

    fn exit_scope(&mut self) {
        self.in_scope.pop();
    }

    fn add_var(&mut self, name: Sym, ty: TypeId) -> VarId {
        let id = VarId(self.seen.len());
        let var = BoundVar {
            id,
            name,
            ty,
            scope: *self
                .in_scope
                .last()
                .expect("enter_scope should be called before add_var"),
        };
        log!("binding var {:?}", var);
        self.seen.push(var);
        id
    }

    fn lookup(&self, name: Sym) -> Option<&BoundVar> {
        self.seen
            .iter()
            .rev()
            .find(|binding| binding.name == name && self.in_scope.contains(&binding.scope))
    }
}

impl TermEnv {
    /// Construct the term environment from the AST and the type environment.
    pub fn from_ast(tyenv: &mut TypeEnv, defs: &ast::Defs) -> Result<TermEnv, Errors> {
        let mut env = TermEnv {
            terms: vec![],
            term_map: StableMap::new(),
            rules: vec![],
            converters: StableMap::new(),
        };

        env.collect_pragmas(defs);
        env.collect_term_sigs(tyenv, defs);
        env.collect_enum_variant_terms(tyenv);
        tyenv.return_errors()?;
        env.collect_constructors(tyenv, defs);
        env.collect_extractor_templates(tyenv, defs);
        tyenv.return_errors()?;
        env.collect_converters(tyenv, defs);
        tyenv.return_errors()?;
        env.collect_externs(tyenv, defs);
        tyenv.return_errors()?;
        env.collect_rules(tyenv, defs);
        env.check_for_undefined_decls(tyenv, defs);
        env.check_for_expr_terms_without_constructors(tyenv, defs);
        tyenv.return_errors()?;

        Ok(env)
    }

    fn collect_pragmas(&mut self, _: &ast::Defs) {
        // currently, no pragmas are defined, but the infrastructure is useful to keep around
        return;
    }

    fn collect_term_sigs(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        for def in &defs.defs {
            match def {
                &ast::Def::Decl(ref decl) => {
                    let name = tyenv.intern_mut(&decl.term);
                    if let Some(tid) = self.term_map.get(&name) {
                        tyenv.report_error(
                            decl.pos,
                            format!("Duplicate decl for '{}'", decl.term.0),
                        );
                        tyenv.report_error(
                            self.terms[tid.index()].decl_pos,
                            format!("Duplicate decl for '{}'", decl.term.0),
                        );
                    }

                    if decl.multi && decl.partial {
                        tyenv.report_error(
                            decl.pos,
                            format!("Term '{}' can't be both multi and partial", decl.term.0),
                        );
                    }

                    let arg_tys = decl
                        .arg_tys
                        .iter()
                        .map(|id| {
                            tyenv.get_type_by_name(id).ok_or_else(|| {
                                tyenv.report_error(id.1, format!("Unknown arg type: '{}'", id.0));
                            })
                        })
                        .collect::<Result<Vec<_>, _>>();
                    let arg_tys = match arg_tys {
                        Ok(a) => a,
                        Err(_) => {
                            continue;
                        }
                    };
                    let ret_ty = match tyenv.get_type_by_name(&decl.ret_ty) {
                        Some(t) => t,
                        None => {
                            tyenv.report_error(
                                decl.ret_ty.1,
                                format!("Unknown return type: '{}'", decl.ret_ty.0),
                            );
                            continue;
                        }
                    };

                    let tid = TermId(self.terms.len());
                    self.term_map.insert(name, tid);
                    let flags = TermFlags {
                        pure: decl.pure,
                        multi: decl.multi,
                        partial: decl.partial,
                    };
                    self.terms.push(Term {
                        id: tid,
                        decl_pos: decl.pos,
                        name,
                        arg_tys,
                        ret_ty,
                        kind: TermKind::Decl {
                            flags,
                            constructor_kind: None,
                            extractor_kind: None,
                        },
                    });
                }
                _ => {}
            }
        }
    }

    fn collect_enum_variant_terms(&mut self, tyenv: &mut TypeEnv) {
        'types: for i in 0..tyenv.types.len() {
            let ty = &tyenv.types[i];
            match ty {
                &Type::Enum {
                    pos,
                    id,
                    ref variants,
                    ..
                } => {
                    for variant in variants {
                        if self.term_map.contains_key(&variant.fullname) {
                            let variant_name = tyenv.syms[variant.fullname.index()].clone();
                            tyenv.report_error(
                                pos,
                                format!("Duplicate enum variant constructor: '{}'", variant_name,),
                            );
                            continue 'types;
                        }
                        let tid = TermId(self.terms.len());
                        let arg_tys = variant.fields.iter().map(|fld| fld.ty).collect::<Vec<_>>();
                        let ret_ty = id;
                        self.terms.push(Term {
                            id: tid,
                            decl_pos: pos,
                            name: variant.fullname,
                            arg_tys,
                            ret_ty,
                            kind: TermKind::EnumVariant {
                                variant: variant.id,
                            },
                        });
                        self.term_map.insert(variant.fullname, tid);
                    }
                }
                _ => {}
            }
        }
    }

    fn collect_constructors(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        for def in &defs.defs {
            log!("collect_constructors from def: {:?}", def);
            match def {
                &ast::Def::Rule(ref rule) => {
                    let pos = rule.pos;
                    let term = match rule.pattern.root_term() {
                        Some(t) => t,
                        None => {
                            tyenv.report_error(
                                pos,
                                "Rule does not have a term at the LHS root".to_string(),
                            );
                            continue;
                        }
                    };
                    let term = match self.get_term_by_name(tyenv, &term) {
                        Some(tid) => tid,
                        None => {
                            tyenv
                                .report_error(pos, "Rule LHS root term is not defined".to_string());
                            continue;
                        }
                    };
                    let termdata = &mut self.terms[term.index()];
                    match &mut termdata.kind {
                        TermKind::Decl {
                            constructor_kind, ..
                        } => {
                            match constructor_kind {
                                None => {
                                    *constructor_kind = Some(ConstructorKind::InternalConstructor);
                                }
                                Some(ConstructorKind::InternalConstructor) => {
                                    // OK, no error; multiple rules can apply to
                                    // one internal constructor term.
                                }
                                Some(ConstructorKind::ExternalConstructor { .. }) => {
                                    tyenv.report_error(
                                        pos,
                                        "Rule LHS root term is incorrect kind; cannot \
                                         be external constructor"
                                            .to_string(),
                                    );
                                    continue;
                                }
                            }
                        }
                        TermKind::EnumVariant { .. } => {
                            tyenv.report_error(
                                pos,
                                "Rule LHS root term is incorrect kind; cannot be enum variant"
                                    .to_string(),
                            );
                            continue;
                        }
                    }
                }
                _ => {}
            }
        }
    }

    fn collect_extractor_templates(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        let mut extractor_call_graph = BTreeMap::new();

        for def in &defs.defs {
            if let &ast::Def::Extractor(ref ext) = def {
                let term = match self.get_term_by_name(tyenv, &ext.term) {
                    Some(x) => x,
                    None => {
                        tyenv.report_error(
                            ext.pos,
                            "Extractor macro body definition on a non-existent term".to_string(),
                        );
                        return;
                    }
                };

                let template = ext.template.make_macro_template(&ext.args[..]);
                log!("extractor def: {:?} becomes template {:?}", def, template);

                let mut callees = BTreeSet::new();
                template.terms(&mut |pos, t| {
                    if let Some(term) = self.get_term_by_name(tyenv, t) {
                        callees.insert(term);
                    } else {
                        tyenv.report_error(
                            pos,
                            format!(
                                "`{}` extractor definition references unknown term `{}`",
                                ext.term.0, t.0
                            ),
                        );
                    }
                });
                extractor_call_graph.insert(term, callees);

                let termdata = &mut self.terms[term.index()];
                match &mut termdata.kind {
                    TermKind::EnumVariant { .. } => {
                        tyenv.report_error(
                            ext.pos,
                            "Extractor macro body defined on term of incorrect kind; cannot be an \
                             enum variant",
                        );
                        continue;
                    }
                    TermKind::Decl {
                        flags,
                        extractor_kind,
                        ..
                    } => match extractor_kind {
                        None => {
                            if flags.multi {
                                tyenv.report_error(
                                    ext.pos,
                                    "A term declared with `multi` cannot have an internal extractor.".to_string());
                                continue;
                            }
                            *extractor_kind = Some(ExtractorKind::InternalExtractor { template });
                        }
                        Some(ext_kind) => {
                            tyenv.report_error(
                                ext.pos,
                                "Duplicate extractor definition".to_string(),
                            );
                            let pos = match ext_kind {
                                ExtractorKind::InternalExtractor { template } => template.pos(),
                                ExtractorKind::ExternalExtractor { pos, .. } => *pos,
                            };
                            tyenv.report_error(
                                pos,
                                "Extractor was already defined here".to_string(),
                            );
                            continue;
                        }
                    },
                }
            }
        }

        // Check for cycles in the extractor call graph.
        let mut stack = vec![];
        'outer: for root in extractor_call_graph.keys().copied() {
            stack.clear();
            stack.push((root, vec![root], StableSet::new()));

            while let Some((caller, path, mut seen)) = stack.pop() {
                let is_new = seen.insert(caller);
                if is_new {
                    if let Some(callees) = extractor_call_graph.get(&caller) {
                        stack.extend(callees.iter().map(|callee| {
                            let mut path = path.clone();
                            path.push(*callee);
                            (*callee, path, seen.clone())
                        }));
                    }
                } else {
                    let pos = match &self.terms[caller.index()].kind {
                        TermKind::Decl {
                            extractor_kind: Some(ExtractorKind::InternalExtractor { template }),
                            ..
                        } => template.pos(),
                        _ => {
                            // There must have already been errors recorded.
                            assert!(!tyenv.errors.is_empty());
                            continue 'outer;
                        }
                    };

                    let path: Vec<_> = path
                        .iter()
                        .map(|sym| tyenv.syms[sym.index()].as_str())
                        .collect();
                    let msg = format!(
                        "`{}` extractor definition is recursive: {}",
                        tyenv.syms[root.index()],
                        path.join(" -> ")
                    );
                    tyenv.report_error(pos, msg);
                    continue 'outer;
                }
            }
        }
    }

    fn collect_converters(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        for def in &defs.defs {
            match def {
                &ast::Def::Converter(ast::Converter {
                    ref term,
                    ref inner_ty,
                    ref outer_ty,
                    pos,
                }) => {
                    let inner_ty_id = match tyenv.get_type_by_name(inner_ty) {
                        Some(ty) => ty,
                        None => {
                            tyenv.report_error(
                                inner_ty.1,
                                format!("Unknown inner type for converter: '{}'", inner_ty.0),
                            );
                            continue;
                        }
                    };

                    let outer_ty_id = match tyenv.get_type_by_name(outer_ty) {
                        Some(ty) => ty,
                        None => {
                            tyenv.report_error(
                                outer_ty.1,
                                format!("Unknown outer type for converter: '{}'", outer_ty.0),
                            );
                            continue;
                        }
                    };

                    let term_id = match self.get_term_by_name(tyenv, term) {
                        Some(term_id) => term_id,
                        None => {
                            tyenv.report_error(
                                term.1,
                                format!("Unknown term for converter: '{}'", term.0),
                            );
                            continue;
                        }
                    };

                    match self.converters.entry((inner_ty_id, outer_ty_id)) {
                        Entry::Vacant(v) => {
                            v.insert(term_id);
                        }
                        Entry::Occupied(_) => {
                            tyenv.report_error(
                                pos,
                                format!(
                                    "Converter already exists for this type pair: '{}', '{}'",
                                    inner_ty.0, outer_ty.0
                                ),
                            );
                            continue;
                        }
                    }
                }
                _ => {}
            }
        }
    }

    fn collect_externs(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        for def in &defs.defs {
            match def {
                &ast::Def::Extern(ast::Extern::Constructor {
                    ref term,
                    ref func,
                    pos,
                }) => {
                    let func_sym = tyenv.intern_mut(func);
                    let term_id = match self.get_term_by_name(tyenv, term) {
                        Some(term) => term,
                        None => {
                            tyenv.report_error(
                                pos,
                                format!("Constructor declared on undefined term '{}'", term.0),
                            );
                            continue;
                        }
                    };
                    let termdata = &mut self.terms[term_id.index()];
                    match &mut termdata.kind {
                        TermKind::Decl {
                            constructor_kind, ..
                        } => match constructor_kind {
                            None => {
                                *constructor_kind =
                                    Some(ConstructorKind::ExternalConstructor { name: func_sym });
                            }
                            Some(ConstructorKind::InternalConstructor) => {
                                tyenv.report_error(
                                    pos,
                                    format!(
                                        "External constructor declared on term that already has rules: {}",
                                        term.0,
                                    ),
                                );
                            }
                            Some(ConstructorKind::ExternalConstructor { .. }) => {
                                tyenv.report_error(
                                    pos,
                                    "Duplicate external constructor definition".to_string(),
                                );
                            }
                        },
                        TermKind::EnumVariant { .. } => {
                            tyenv.report_error(
                                pos,
                                format!(
                                    "External constructor cannot be defined on enum variant: {}",
                                    term.0,
                                ),
                            );
                        }
                    }
                }
                &ast::Def::Extern(ast::Extern::Extractor {
                    ref term,
                    ref func,
                    pos,
                    infallible,
                }) => {
                    let func_sym = tyenv.intern_mut(func);
                    let term_id = match self.get_term_by_name(tyenv, term) {
                        Some(term) => term,
                        None => {
                            tyenv.report_error(
                                pos,
                                format!("Extractor declared on undefined term '{}'", term.0),
                            );
                            continue;
                        }
                    };

                    let termdata = &mut self.terms[term_id.index()];

                    match &mut termdata.kind {
                        TermKind::Decl { extractor_kind, .. } => match extractor_kind {
                            None => {
                                *extractor_kind = Some(ExtractorKind::ExternalExtractor {
                                    name: func_sym,
                                    infallible,
                                    pos,
                                });
                            }
                            Some(ExtractorKind::ExternalExtractor { pos: pos2, .. }) => {
                                tyenv.report_error(
                                    pos,
                                    "Duplicate external extractor definition".to_string(),
                                );
                                tyenv.report_error(
                                    *pos2,
                                    "External extractor already defined".to_string(),
                                );
                                continue;
                            }
                            Some(ExtractorKind::InternalExtractor { template }) => {
                                tyenv.report_error(
                                    pos,
                                    "Cannot define external extractor for term that already has an \
                                     internal extractor macro body defined"
                                        .to_string(),
                                );
                                tyenv.report_error(
                                    template.pos(),
                                    "Internal extractor macro body already defined".to_string(),
                                );
                                continue;
                            }
                        },
                        TermKind::EnumVariant { .. } => {
                            tyenv.report_error(
                                pos,
                                format!("Cannot define extractor for enum variant '{}'", term.0),
                            );
                            continue;
                        }
                    }
                }
                _ => {}
            }
        }
    }

    fn collect_rules(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        for def in &defs.defs {
            match def {
                &ast::Def::Rule(ref rule) => {
                    let pos = rule.pos;
                    let mut bindings = Bindings::default();
                    bindings.enter_scope();

                    let (sym, args) = if let ast::Pattern::Term { sym, args, .. } = &rule.pattern {
                        (sym, args)
                    } else {
                        tyenv.report_error(
                            pos,
                            "Rule does not have a term at the root of its left-hand side"
                                .to_string(),
                        );
                        continue;
                    };

                    let root_term = if let Some(term) = self.get_term_by_name(tyenv, sym) {
                        term
                    } else {
                        tyenv.report_error(
                            pos,
                            "Cannot define a rule for an unknown term".to_string(),
                        );
                        continue;
                    };

                    let termdata = &self.terms[root_term.index()];

                    let flags = match &termdata.kind {
                        TermKind::Decl { flags, .. } => flags,
                        _ => {
                            tyenv.report_error(
                                pos,
                                "Cannot define a rule on a left-hand-side that is an enum variant"
                                    .to_string(),
                            );
                            continue;
                        }
                    };

                    termdata.check_args_count(args, tyenv, pos, sym);
                    let args = self.translate_args(args, termdata, tyenv, &mut bindings);

                    let iflets = rule
                        .iflets
                        .iter()
                        .filter_map(|iflet| {
                            self.translate_iflet(tyenv, iflet, &mut bindings, flags)
                        })
                        .collect();
                    let rhs = unwrap_or_continue!(self.translate_expr(
                        tyenv,
                        &rule.expr,
                        Some(termdata.ret_ty),
                        &mut bindings,
                        flags,
                        /* on_lhs */ false,
                    ));

                    bindings.exit_scope();

                    let prio = if let Some(prio) = rule.prio {
                        if flags.multi {
                            tyenv.report_error(
                                pos,
                                "Cannot set rule priorities in multi-terms".to_string(),
                            );
                        }
                        prio
                    } else {
                        0
                    };

                    let rid = RuleId(self.rules.len());
                    self.rules.push(Rule {
                        id: rid,
                        root_term,
                        args,
                        iflets,
                        rhs,
                        vars: bindings.seen,
                        prio,
                        pos,
                    });
                }
                _ => {}
            }
        }
    }

    fn check_for_undefined_decls(&self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        for def in &defs.defs {
            if let ast::Def::Decl(decl) = def {
                let term = self.get_term_by_name(tyenv, &decl.term).unwrap();
                let term = &self.terms[term.index()];
                if !term.has_constructor() && !term.has_extractor() {
                    tyenv.report_error(
                        decl.pos,
                        format!(
                            "no rules, extractor, or external definition for declaration '{}'",
                            decl.term.0
                        ),
                    );
                }
            }
        }
    }

    fn check_for_expr_terms_without_constructors(&self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
        for def in &defs.defs {
            if let ast::Def::Rule(rule) = def {
                rule.expr.terms(&mut |pos, ident| {
                    let term = match self.get_term_by_name(tyenv, ident) {
                        None => {
                            debug_assert!(!tyenv.errors.is_empty());
                            return;
                        }
                        Some(t) => t,
                    };
                    let term = &self.terms[term.index()];
                    if !term.has_constructor() {
                        tyenv.report_error(
                            pos,
                            format!(
                                "term `{}` cannot be used in an expression because \
                                 it does not have a constructor",
                                ident.0
                            ),
                        )
                    }
                });
            }
        }
    }

    fn maybe_implicit_convert_pattern(
        &self,
        tyenv: &mut TypeEnv,
        pattern: &ast::Pattern,
        inner_ty: TypeId,
        outer_ty: TypeId,
    ) -> Option<ast::Pattern> {
        if let Some(converter_term) = self.converters.get(&(inner_ty, outer_ty)) {
            if self.terms[converter_term.index()].has_extractor() {
                // This is a little awkward: we have to
                // convert back to an Ident, to be
                // re-resolved. The pos doesn't matter
                // as it shouldn't result in a lookup
                // failure.
                let converter_term_ident = ast::Ident(
                    tyenv.syms[self.terms[converter_term.index()].name.index()].clone(),
                    pattern.pos(),
                );
                let expanded_pattern = ast::Pattern::Term {
                    sym: converter_term_ident,
                    pos: pattern.pos(),
                    args: vec![pattern.clone()],
                };

                return Some(expanded_pattern);
            }
        }
        None
    }

    fn translate_pattern(
        &self,
        tyenv: &mut TypeEnv,
        pat: &ast::Pattern,
        expected_ty: TypeId,
        bindings: &mut Bindings,
    ) -> Option<Pattern> {
        log!("translate_pattern: {:?}", pat);
        log!("translate_pattern: bindings = {:?}", bindings);
        match pat {
            // TODO: flag on primitive type decl indicating it's an integer type?
            &ast::Pattern::ConstInt { val, pos } => {
                let ty = &tyenv.types[expected_ty.index()];
                if !ty.is_prim() {
                    tyenv.report_error(
                        pos,
                        format!(
                            "expected non-primitive type {}, but found integer literal '{}'",
                            ty.name(tyenv),
                            val,
                        ),
                    );
                }
                Some(Pattern::ConstInt(expected_ty, val))
            }
            &ast::Pattern::ConstPrim { ref val, pos } => {
                let val = tyenv.intern_mut(val);
                let const_ty = match tyenv.const_types.get(&val) {
                    Some(ty) => *ty,
                    None => {
                        tyenv.report_error(pos, "Unknown constant");
                        return None;
                    }
                };
                if expected_ty != const_ty {
                    tyenv.report_error(pos, "Type mismatch for constant");
                }
                Some(Pattern::ConstPrim(const_ty, val))
            }
            &ast::Pattern::Wildcard { .. } => Some(Pattern::Wildcard(expected_ty)),
            &ast::Pattern::And { ref subpats, .. } => {
                // If any of the subpatterns fails to type-check, we'll report
                // an error at that point. Here, just skip it and keep looking
                // for more errors.
                let children = subpats
                    .iter()
                    .filter_map(|subpat| {
                        self.translate_pattern(tyenv, subpat, expected_ty, bindings)
                    })
                    .collect();
                Some(Pattern::And(expected_ty, children))
            }
            &ast::Pattern::BindPattern {
                ref var,
                ref subpat,
                pos,
            } => {
                let subpat = self.translate_pattern(tyenv, subpat, expected_ty, bindings)?;

                // The sub-pattern's type should be `expected_ty`. If it isn't,
                // we've already reported a type error about it, but continue
                // using the type we actually found in hopes that we'll
                // generate fewer follow-on error messages.
                let ty = subpat.ty();

                let name = tyenv.intern_mut(var);
                if bindings.lookup(name).is_some() {
                    tyenv.report_error(
                        pos,
                        format!("Re-bound variable name in LHS pattern: '{}'", var.0),
                    );
                    // Try to keep going.
                }
                let id = bindings.add_var(name, ty);
                Some(Pattern::BindPattern(ty, id, Box::new(subpat)))
            }
            &ast::Pattern::Var { ref var, pos } => {
                // Look up the variable; if it has already been bound,
                // then this becomes a `Var` node (which matches the
                // existing bound value), otherwise it becomes a
                // `BindPattern` with a wildcard subpattern to capture
                // at this location.
                let name = tyenv.intern_mut(var);
                match bindings.lookup(name) {
                    None => {
                        let id = bindings.add_var(name, expected_ty);
                        Some(Pattern::BindPattern(
                            expected_ty,
                            id,
                            Box::new(Pattern::Wildcard(expected_ty)),
                        ))
                    }
                    Some(bv) => {
                        if expected_ty != bv.ty {
                            tyenv.report_error(
                                pos,
                                format!(
                                    "Mismatched types: pattern expects type '{}' but already-bound var '{}' has type '{}'",
                                    tyenv.types[expected_ty.index()].name(tyenv),
                                    var.0,
                                    tyenv.types[bv.ty.index()].name(tyenv),
                                ),
                            );
                            // Try to keep going for more errors.
                        }
                        Some(Pattern::Var(bv.ty, bv.id))
                    }
                }
            }
            &ast::Pattern::Term {
                ref sym,
                ref args,
                pos,
            } => {
                // Look up the term.
                let tid = match self.get_term_by_name(tyenv, sym) {
                    Some(t) => t,
                    None => {
                        tyenv.report_error(pos, format!("Unknown term in pattern: '{}'", sym.0));
                        return None;
                    }
                };

                let termdata = &self.terms[tid.index()];

                // Get the return type and arg types. Verify the
                // expected type of this pattern, if any, against the
                // return type of the term. Insert an implicit
                // converter if needed.
                let ret_ty = termdata.ret_ty;
                if expected_ty != ret_ty {
                    // Can we do an implicit type conversion? Look
                    // up the converter term, if any. If one has
                    // been registered, and the term has an
                    // extractor, then build an expanded AST node
                    // right here and recurse on it.
                    if let Some(expanded_pattern) =
                        self.maybe_implicit_convert_pattern(tyenv, pat, ret_ty, expected_ty)
                    {
                        return self.translate_pattern(
                            tyenv,
                            &expanded_pattern,
                            expected_ty,
                            bindings,
                        );
                    }

                    tyenv.report_error(
                        pos,
                        format!(
                            "Mismatched types: pattern expects type '{}' but term has return type '{}'",
                            tyenv.types[expected_ty.index()].name(tyenv),
                            tyenv.types[ret_ty.index()].name(tyenv),
                        ),
                    );
                    // Try to keep going for more errors.
                }

                termdata.check_args_count(args, tyenv, pos, sym);

                // TODO: check that multi-extractors are only used in terms declared `multi`

                match &termdata.kind {
                    TermKind::EnumVariant { .. } => {}
                    TermKind::Decl {
                        extractor_kind: Some(ExtractorKind::ExternalExtractor { .. }),
                        ..
                    } => {}
                    TermKind::Decl {
                        extractor_kind: Some(ExtractorKind::InternalExtractor { ref template }),
                        ..
                    } => {
                        // Expand the extractor macro! We create a map
                        // from macro args to AST pattern trees and
                        // then evaluate the template with these
                        // substitutions.
                        log!("internal extractor macro args = {:?}", args);
                        let pat = template.subst_macro_args(&args)?;
                        return self.translate_pattern(tyenv, &pat, expected_ty, bindings);
                    }
                    TermKind::Decl {
                        extractor_kind: None,
                        ..
                    } => {
                        tyenv.report_error(
                            pos,
                            format!(
                                "Cannot use term '{}' that does not have a defined extractor in a \
                                 left-hand side pattern",
                                sym.0
                            ),
                        );
                    }
                }

                let subpats = self.translate_args(args, termdata, tyenv, bindings);
                Some(Pattern::Term(ret_ty, tid, subpats))
            }
            &ast::Pattern::MacroArg { .. } => unreachable!(),
        }
    }

    fn translate_args(
        &self,
        args: &Vec<ast::Pattern>,
        termdata: &Term,
        tyenv: &mut TypeEnv,
        bindings: &mut Bindings,
    ) -> Vec<Pattern> {
        args.iter()
            .zip(termdata.arg_tys.iter())
            .filter_map(|(arg, &arg_ty)| self.translate_pattern(tyenv, arg, arg_ty, bindings))
            .collect()
    }

    fn maybe_implicit_convert_expr(
        &self,
        tyenv: &mut TypeEnv,
        expr: &ast::Expr,
        inner_ty: TypeId,
        outer_ty: TypeId,
    ) -> Option<ast::Expr> {
        // Is there a converter for this type mismatch?
        if let Some(converter_term) = self.converters.get(&(inner_ty, outer_ty)) {
            if self.terms[converter_term.index()].has_constructor() {
                let converter_ident = ast::Ident(
                    tyenv.syms[self.terms[converter_term.index()].name.index()].clone(),
                    expr.pos(),
                );
                return Some(ast::Expr::Term {
                    sym: converter_ident,
                    pos: expr.pos(),
                    args: vec![expr.clone()],
                });
            }
        }
        None
    }

    fn translate_expr(
        &self,
        tyenv: &mut TypeEnv,
        expr: &ast::Expr,
        ty: Option<TypeId>,
        bindings: &mut Bindings,
        root_flags: &TermFlags,
        on_lhs: bool,
    ) -> Option<Expr> {
        log!("translate_expr: {:?}", expr);
        match expr {
            &ast::Expr::Term {
                ref sym,
                ref args,
                pos,
            } => {
                // Look up the term.
                let name = tyenv.intern_mut(&sym);
                let tid = match self.term_map.get(&name) {
                    Some(&t) => t,
                    None => {
                        // Maybe this was actually a variable binding and the user has placed
                        // parens around it by mistake? (See #4775.)
                        if bindings.lookup(name).is_some() {
                            tyenv.report_error(
                                pos,
                                format!(
                                    "Unknown term in expression: '{}'. Variable binding under this name exists; try removing the parens?", sym.0));
                        } else {
                            tyenv.report_error(
                                pos,
                                format!("Unknown term in expression: '{}'", sym.0),
                            );
                        }
                        return None;
                    }
                };
                let termdata = &self.terms[tid.index()];

                // Get the return type and arg types. Verify the
                // expected type of this pattern, if any, against the
                // return type of the term, and determine whether we
                // are doing an implicit conversion. Report an error
                // if types don't match and no conversion is possible.
                let ret_ty = termdata.ret_ty;
                let ty = if ty.is_some() && ret_ty != ty.unwrap() {
                    // Is there a converter for this type mismatch?
                    if let Some(expanded_expr) =
                        self.maybe_implicit_convert_expr(tyenv, expr, ret_ty, ty.unwrap())
                    {
                        return self.translate_expr(
                            tyenv,
                            &expanded_expr,
                            ty,
                            bindings,
                            root_flags,
                            on_lhs,
                        );
                    }

                    tyenv.report_error(
                        pos,
                        format!("Mismatched types: expression expects type '{}' but term has return type '{}'",
                                tyenv.types[ty.unwrap().index()].name(tyenv),
                                tyenv.types[ret_ty.index()].name(tyenv)));

                    // Keep going, to discover more errors.
                    ret_ty
                } else {
                    ret_ty
                };

                if let TermKind::Decl { flags, .. } = &termdata.kind {
                    // On the left-hand side of a rule or in a pure term, only pure terms may be
                    // used.
                    let pure_required = on_lhs || root_flags.pure;
                    if pure_required && !flags.pure {
                        tyenv.report_error(
                            pos,
                            format!(
                                "Used non-pure constructor '{}' in pure expression context",
                                sym.0
                            ),
                        );
                    }

                    // Multi-terms may only be used inside other multi-terms.
                    if !root_flags.multi && flags.multi {
                        tyenv.report_error(
                            pos,
                            format!(
                                "Used multi-constructor '{}' but this rule is not in a multi-term",
                                sym.0
                            ),
                        );
                    }

                    // Partial terms may always be used on the left-hand side of a rule. On the
                    // right-hand side they may only be used inside other partial terms.
                    let partial_allowed = on_lhs || root_flags.partial;
                    if !partial_allowed && flags.partial {
                        tyenv.report_error(
                            pos,
                            format!(
                                "Rule can't use partial constructor '{}' on RHS; \
                                try moving it to if-let{}",
                                sym.0,
                                if root_flags.multi {
                                    ""
                                } else {
                                    " or make this rule's term partial too"
                                }
                            ),
                        );
                    }
                }

                termdata.check_args_count(args, tyenv, pos, sym);

                // Resolve subexpressions.
                let subexprs = args
                    .iter()
                    .zip(termdata.arg_tys.iter())
                    .filter_map(|(arg, &arg_ty)| {
                        self.translate_expr(tyenv, arg, Some(arg_ty), bindings, root_flags, on_lhs)
                    })
                    .collect();

                Some(Expr::Term(ty, tid, subexprs))
            }
            &ast::Expr::Var { ref name, pos } => {
                let sym = tyenv.intern_mut(name);
                // Look through bindings, innermost (most recent) first.
                let bv = match bindings.lookup(sym) {
                    None => {
                        tyenv.report_error(pos, format!("Unknown variable '{}'", name.0));
                        return None;
                    }
                    Some(bv) => bv,
                };

                // Verify type. Maybe do an implicit conversion.
                if ty.is_some() && bv.ty != ty.unwrap() {
                    // Is there a converter for this type mismatch?
                    if let Some(expanded_expr) =
                        self.maybe_implicit_convert_expr(tyenv, expr, bv.ty, ty.unwrap())
                    {
                        return self.translate_expr(
                            tyenv,
                            &expanded_expr,
                            ty,
                            bindings,
                            root_flags,
                            on_lhs,
                        );
                    }

                    tyenv.report_error(
                        pos,
                        format!(
                            "Variable '{}' has type {} but we need {} in context",
                            name.0,
                            tyenv.types[bv.ty.index()].name(tyenv),
                            tyenv.types[ty.unwrap().index()].name(tyenv)
                        ),
                    );
                }

                Some(Expr::Var(bv.ty, bv.id))
            }
            &ast::Expr::ConstInt { val, pos } => {
                if ty.is_none() {
                    tyenv.report_error(
                        pos,
                        "integer literal in a context that needs an explicit type".to_string(),
                    );
                    return None;
                }
                let ty = ty.unwrap();

                if !tyenv.types[ty.index()].is_prim() {
                    tyenv.report_error(
                        pos,
                        format!(
                            "expected non-primitive type {}, but found integer literal '{}'",
                            tyenv.types[ty.index()].name(tyenv),
                            val,
                        ),
                    );
                }
                Some(Expr::ConstInt(ty, val))
            }
            &ast::Expr::ConstPrim { ref val, pos } => {
                let val = tyenv.intern_mut(val);
                let const_ty = match tyenv.const_types.get(&val) {
                    Some(ty) => *ty,
                    None => {
                        tyenv.report_error(pos, "Unknown constant");
                        return None;
                    }
                };
                if ty.is_some() && const_ty != ty.unwrap() {
                    tyenv.report_error(
                        pos,
                        format!(
                            "Constant '{}' has wrong type: expected {}, but is actually {}",
                            tyenv.syms[val.index()],
                            tyenv.types[ty.unwrap().index()].name(tyenv),
                            tyenv.types[const_ty.index()].name(tyenv)
                        ),
                    );
                    return None;
                }
                Some(Expr::ConstPrim(const_ty, val))
            }
            &ast::Expr::Let {
                ref defs,
                ref body,
                pos,
            } => {
                bindings.enter_scope();

                // For each new binding...
                let mut let_defs = vec![];
                for def in defs {
                    // Check that the given variable name does not already exist.
                    let name = tyenv.intern_mut(&def.var);

                    // Look up the type.
                    let tid = match tyenv.get_type_by_name(&def.ty) {
                        Some(tid) => tid,
                        None => {
                            tyenv.report_error(
                                pos,
                                format!("Unknown type {} for variable '{}'", def.ty.0, def.var.0),
                            );
                            continue;
                        }
                    };

                    // Evaluate the variable's value.
                    let val = Box::new(unwrap_or_continue!(self.translate_expr(
                        tyenv,
                        &def.val,
                        Some(tid),
                        bindings,
                        root_flags,
                        on_lhs,
                    )));

                    // Bind the var with the given type.
                    let id = bindings.add_var(name, tid);
                    let_defs.push((id, tid, val));
                }

                // Evaluate the body, expecting the type of the overall let-expr.
                let body =
                    Box::new(self.translate_expr(tyenv, body, ty, bindings, root_flags, on_lhs)?);
                let body_ty = body.ty();

                // Pop the bindings.
                bindings.exit_scope();

                Some(Expr::Let {
                    ty: body_ty,
                    bindings: let_defs,
                    body,
                })
            }
        }
    }

    fn translate_iflet(
        &self,
        tyenv: &mut TypeEnv,
        iflet: &ast::IfLet,
        bindings: &mut Bindings,
        root_flags: &TermFlags,
    ) -> Option<IfLet> {
        // Translate the expr first. The `if-let` and `if` forms are part of the left-hand side of
        // the rule.
        let rhs = self.translate_expr(
            tyenv,
            &iflet.expr,
            None,
            bindings,
            root_flags,
            /* on_lhs */ true,
        )?;
        let lhs = self.translate_pattern(tyenv, &iflet.pattern, rhs.ty(), bindings)?;

        Some(IfLet { lhs, rhs })
    }

    fn get_term_by_name(&self, tyenv: &TypeEnv, sym: &ast::Ident) -> Option<TermId> {
        tyenv
            .intern(sym)
            .and_then(|sym| self.term_map.get(&sym))
            .copied()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::ast::Ident;
    use crate::lexer::Lexer;
    use crate::parser::parse;

    #[test]
    fn build_type_env() {
        let text = r"
            (type u32 (primitive u32))
            (type A extern (enum (B (f1 u32) (f2 u32)) (C (f1 u32))))
        ";
        let ast = parse(Lexer::from_str(text, "file.isle").unwrap()).expect("should parse");
        let tyenv = TypeEnv::from_ast(&ast).expect("should not have type-definition errors");

        let sym_a = tyenv
            .intern(&Ident("A".to_string(), Default::default()))
            .unwrap();
        let sym_b = tyenv
            .intern(&Ident("B".to_string(), Default::default()))
            .unwrap();
        let sym_c = tyenv
            .intern(&Ident("C".to_string(), Default::default()))
            .unwrap();
        let sym_a_b = tyenv
            .intern(&Ident("A.B".to_string(), Default::default()))
            .unwrap();
        let sym_a_c = tyenv
            .intern(&Ident("A.C".to_string(), Default::default()))
            .unwrap();
        let sym_u32 = tyenv
            .intern(&Ident("u32".to_string(), Default::default()))
            .unwrap();
        let sym_f1 = tyenv
            .intern(&Ident("f1".to_string(), Default::default()))
            .unwrap();
        let sym_f2 = tyenv
            .intern(&Ident("f2".to_string(), Default::default()))
            .unwrap();

        assert_eq!(tyenv.type_map.get(&sym_u32).unwrap(), &TypeId(0));
        assert_eq!(tyenv.type_map.get(&sym_a).unwrap(), &TypeId(1));

        let expected_types = vec![
            Type::Primitive(
                TypeId(0),
                sym_u32,
                Pos {
                    file: 0,
                    offset: 19,
                    line: 2,
                    col: 18,
                },
            ),
            Type::Enum {
                name: sym_a,
                id: TypeId(1),
                is_extern: true,
                is_nodebug: false,
                variants: vec![
                    Variant {
                        name: sym_b,
                        fullname: sym_a_b,
                        id: VariantId(0),
                        fields: vec![
                            Field {
                                name: sym_f1,
                                id: FieldId(0),
                                ty: TypeId(0),
                            },
                            Field {
                                name: sym_f2,
                                id: FieldId(1),
                                ty: TypeId(0),
                            },
                        ],
                    },
                    Variant {
                        name: sym_c,
                        fullname: sym_a_c,
                        id: VariantId(1),
                        fields: vec![Field {
                            name: sym_f1,
                            id: FieldId(0),
                            ty: TypeId(0),
                        }],
                    },
                ],
                pos: Pos {
                    file: 0,
                    offset: 58,
                    line: 3,
                    col: 18,
                },
            },
        ];

        assert_eq!(tyenv.types.len(), expected_types.len());
        for (i, (actual, expected)) in tyenv.types.iter().zip(&expected_types).enumerate() {
            assert_eq!(expected, actual, "`{}`th type is not equal!", i);
        }
    }
}
