#![allow(non_snake_case)] use std::collections::BTreeMap; use std::collections::HashMap; use std::rc::Rc; use crate::context::Context; use crate::visitor; use crate::*; pub type Integer = isize; pub type Natural = usize; pub type Double = NaiveDouble; /// An empty type #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum X {} pub fn trivial_result(x: Result) -> T { match x { Ok(x) => x, Err(e) => match e {}, } } /// Double with bitwise equality #[derive(Debug, Copy, Clone)] pub struct NaiveDouble(f64); impl PartialEq for NaiveDouble { fn eq(&self, other: &Self) -> bool { self.0.to_bits() == other.0.to_bits() } } impl Eq for NaiveDouble {} impl From for NaiveDouble { fn from(x: f64) -> Self { NaiveDouble(x) } } impl From for f64 { fn from(x: NaiveDouble) -> f64 { x.0 } } /// Constants for a pure type system #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Const { Type, Kind, Sort, } /// Bound variable /// /// The `Label` field is the variable's name (i.e. \"`x`\"). /// The `Int` field is a DeBruijn index. /// See dhall-lang/standard/semantics.md for details #[derive(Debug, Clone, PartialEq, Eq)] pub struct Var(pub VarLabel, pub usize); // Definition order must match precedence order for // pretty-printing to work correctly #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum BinOp { /// x ? y ImportAlt, /// x || y` BoolOr, /// x + y` NaturalPlus, /// x ++ y` TextAppend, /// x # y ListAppend, /// x && y` BoolAnd, /// x ∧ y` Combine, /// x // y Prefer, /// x //\\ y CombineTypes, /// x * y` NaturalTimes, /// x == y` BoolEQ, /// x != y` BoolNE, } /// Built-ins #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Builtin { Bool, Natural, Integer, Double, Text, List, Optional, OptionalNone, NaturalBuild, NaturalFold, NaturalIsZero, NaturalEven, NaturalOdd, NaturalToInteger, NaturalShow, IntegerToDouble, IntegerShow, DoubleShow, ListBuild, ListFold, ListLength, ListHead, ListLast, ListIndexed, ListReverse, OptionalFold, OptionalBuild, TextShow, } pub type ParsedExpr = SubExpr; pub type ResolvedExpr = SubExpr; pub type DhallExpr = ResolvedExpr; // Each node carries an annotation. In practice it's either X (no annotation) or a Span. #[derive(Debug)] pub struct SubExpr( Rc<(Expr, Option)>, ); impl std::cmp::PartialEq for SubExpr { fn eq(&self, other: &Self) -> bool { self.0.as_ref().0 == other.0.as_ref().0 } } impl std::cmp::Eq for SubExpr { } pub type Expr = ExprF, VarLabel, Embed>; /// Syntax tree for expressions // Having the recursion out of the enum definition enables writing // much more generic code and improves pattern-matching behind // smart pointers. #[derive(Debug, Clone, PartialEq, Eq)] pub enum ExprF { Const(Const), /// `x` /// `x@n` Var(Var), /// `λ(x : A) -> b` Lam(VarLabel, SubExpr, SubExpr), /// `A -> B` /// `∀(x : A) -> B` Pi(VarLabel, SubExpr, SubExpr), /// `f a` App(SubExpr, SubExpr), /// `let x = r in e` /// `let x : t = r in e` Let(VarLabel, Option, SubExpr, SubExpr), /// `x : t` Annot(SubExpr, SubExpr), /// Built-in values Builtin(Builtin), // Binary operations BinOp(BinOp, SubExpr, SubExpr), /// `True` BoolLit(bool), /// `if x then y else z` BoolIf(SubExpr, SubExpr, SubExpr), /// `1` NaturalLit(Natural), /// `+2` IntegerLit(Integer), /// `3.24` DoubleLit(Double), /// `"Some ${interpolated} text"` TextLit(InterpolatedText), /// `[] : List t` EmptyListLit(SubExpr), /// `[x, y, z]` NEListLit(Vec), /// Deprecated Optional literal form /// `[] : Optional a` /// `[x] : Optional a` OldOptionalLit(Option, SubExpr), /// `Some e` SomeLit(SubExpr), /// `{ k1 : t1, k2 : t1 }` RecordType(BTreeMap), /// `{ k1 = v1, k2 = v2 }` RecordLit(BTreeMap), /// `< k1 : t1, k2 >` UnionType(BTreeMap>), /// `< k1 = t1, k2 : t2, k3 >` UnionLit(Label, SubExpr, BTreeMap>), /// `merge x y : t` Merge(SubExpr, SubExpr, Option), /// `e.x` Field(SubExpr, Label), /// `e.{ x, y, z }` Projection(SubExpr, Vec