#![allow(non_snake_case)] use crate::*; use std::collections::BTreeMap; use std::rc::Rc; pub type Int = isize; pub type Integer = isize; pub type Natural = usize; pub type Double = NaiveDouble; /// An empty type #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum X {} /// Double with bitwise equality #[derive(Debug, Copy, Clone)] pub struct NaiveDouble(f64); impl PartialEq for NaiveDouble { fn eq(&self, other: &Self) -> bool { return 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 /// /// The only axiom is: /// /// ```c /// ⊦ Type : Kind /// ``` /// /// ... and the valid rule pairs are: /// /// ```c /// ⊦ Type ↝ Type : Type -- Functions from terms to terms (ordinary functions) /// ⊦ Kind ↝ Type : Type -- Functions from types to terms (polymorphic functions) /// ⊦ Kind ↝ Kind : Kind -- Functions from types to types (type constructors) /// ``` /// /// These are the same rule pairs as System Fω /// /// Note that Dhall does not support functions from terms to types and therefore /// Dhall is not a dependently typed language /// #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Const { Type, Kind, } /// Bound variable /// /// The `Label` field is the variable's name (i.e. \"`x`\"). /// /// The `Int` field disambiguates variables with the same name if there are /// multiple bound variables of the same name in scope. Zero refers to the /// nearest bound variable and the index increases by one for each bound /// variable of the same name going outward. The following diagram may help: /// /// ```c /// +---refers to--+ /// | | /// v | /// \(x : Type) -> \(y : Type) -> \(x : Type) -> x@0 /// /// +------------------refers to-----------------+ /// | | /// v | /// \(x : Type) -> \(y : Type) -> \(x : Type) -> x@1 /// ``` /// /// This `Int` behaves like a De Bruijn index in the special case where all /// variables have the same name. /// /// You can optionally omit the index if it is `0`: /// /// ```c /// +refers to+ /// | | /// v | /// \(x : *) -> \(y : *) -> \(x : *) -> x /// ``` /// /// Zero indices are omitted when pretty-printing `Var`s and non-zero indices /// appear as a numeric suffix. /// #[derive(Debug, Clone, PartialEq, Eq)] pub struct V(pub Label, 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, OptionalSome, 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; pub type SubExpr = Rc>; /// Syntax tree for expressions #[derive(Debug, Clone, PartialEq, Eq)] pub enum Expr { /// `Const c ~ c` Const(Const), /// `Var (V x 0) ~ x`
/// `Var (V x n) ~ x@n` Var(V), /// `Lam x A b ~ λ(x : A) -> b` Lam(Label, SubExpr, SubExpr), /// `Pi "_" A B ~ A -> B` /// `Pi x A B ~ ∀(x : A) -> B` Pi(Label, SubExpr, SubExpr), /// `App f A ~ f A` App(SubExpr, Vec>), /// `Let x Nothing r e ~ let x = r in e` /// `Let x (Just t) r e ~ let x : t = r in e` Let( Label, Option>, SubExpr, SubExpr, ), /// `Annot x t ~ x : t` Annot(SubExpr, SubExpr), /// Built-in values Builtin(Builtin), // Binary operations BinOp(BinOp, SubExpr, SubExpr), /// `BoolLit b ~ b` BoolLit(bool), /// `BoolIf x y z ~ if x then y else z` BoolIf( SubExpr, SubExpr, SubExpr, ), /// `NaturalLit n ~ +n` NaturalLit(Natural), /// `IntegerLit n ~ n` IntegerLit(Integer), /// `DoubleLit n ~ n` DoubleLit(Double), /// `TextLit t ~ t` TextLit(InterpolatedText), /// [] : List t` EmptyListLit(SubExpr), /// [x, y, z] NEListLit(Vec>), /// None t EmptyOptionalLit(SubExpr), /// Some e NEOptionalLit(SubExpr), /// `Record [(k1, t1), (k2, t2)] ~ { k1 : t1, k2 : t1 }` RecordType(BTreeMap>), /// `RecordLit [(k1, v1), (k2, v2)] ~ { k1 = v1, k2 = v2 }` RecordLit(BTreeMap>), /// `Union [(k1, t1), (k2, t2)] ~ < k1 : t1, k2 : t2 >` UnionType(BTreeMap>), /// `UnionLit (k1, v1) [(k2, t2), (k3, t3)] ~ < k1 = t1, k2 : t2, k3 : t3 >` UnionLit( Label, SubExpr, BTreeMap>, ), /// `Merge x y t ~ merge x y : t` Merge( SubExpr, SubExpr, Option>, ), /// e.x Field(SubExpr, Label), /// e.{ x, y, z } Projection(SubExpr, Vec