fn build_ineq(&mut self, sp: &FileSpan, args: Vec<LispVal>, op: Binop) -> Result<ast::ExprKind> {
    // Haskell pseudocode:
    // build_ineq [] = error
    // build_ineq [e1] = { e1; true }
    // build_ineq [e1, e2] = e1 < e2
    // build_ineq (e1:e2:e3:es) = { let v1 = e1; let v2 = e2; mk_and v1 v2 e3 es }
    // mk_and v0 v1 e2 es = (v0 < v1 && mk_block v1 e2 es)
    // mk_block v1 e2 [] = (v1 < e2)
    // mk_block v1 e2 (e3:es) = { let v2 = e2; mk_and v1 v2 e3 es }

    macro_rules! sp {($sp:expr, $k:expr) => {Spanned {span: $sp.clone(), k: $k}}}
    macro_rules! binop {($sp:expr, $op:expr, $e1:expr, $e2:expr) => {
      sp!($sp, ast::ExprKind::binop($sp, $op, $e1, $e2))
    }}
    macro_rules! block {($($e:expr),*; $last:expr) => {
      ast::ExprKind::Block(ast::Block {stmts: vec![$($e),*], expr: Some(Box::new($last))})
    }}
    fn binop(sp: &FileSpan, op: Binop, v1: VarId, e2: ast::Expr) -> ast::Expr {
      binop!(sp, op, sp!(sp, ast::ExprKind::Var(v1)), e2)
    }
    fn and(sp: &FileSpan, op: Binop, v1: VarId, v2: VarId, e: ast::Expr) -> ast::Expr {
      binop!(sp, Binop::And, binop(sp, op, v1, sp!(sp, ast::ExprKind::Var(v2))), e)
    }
    let mut it = args.into_iter();
    let arg_1 = it.next().ok_or_else(|| ElabError::new_e(sp, "inequality: syntax error"))?;
    let arg_1 = self.build_expr(sp, arg_1)?;
    Ok(if let Some(arg_2) = it.next() {
      let arg_2 = self.build_expr(sp, arg_2)?;
      if let Some(arg_3) = it.next() {
        fn mk_and(this: &mut BuildAst<'_>, sp: &FileSpan, op: Binop, v0: VarId, v1: VarId, e2: LispVal,
          mut it: std::vec::IntoIter<LispVal>
        ) -> Result<ast::Expr> {
          let e2 = this.build_expr(sp, e2)?;
          Ok(and(sp, op, v0, v1, if let Some(e3) = it.next() {
            let v2 = this.fresh_var(AtomId::UNDER);
            sp!(sp, block![
              let_var(sp, AtomId::UNDER, v2, e2);
              mk_and(this, sp, op, v1, v2, e3, it)?
            ])
          } else {
            binop(sp, op, v1, e2)
          }))
        }
        let v_1 = self.fresh_var(AtomId::UNDER);
        let v_2 = self.fresh_var(AtomId::UNDER);
        block![
          let_var(sp, AtomId::UNDER, v_1, arg_1),
          let_var(sp, AtomId::UNDER, v_2, arg_2);
          mk_and(self, sp, op, v_1, v_2, arg_3, it)?
        ]
      } else {
        ast::ExprKind::binop(sp, op, arg_1, arg_2)
      }
    } else {
      block![arg_1.map_into(ast::StmtKind::Expr); sp!(sp, ast::ExprKind::Bool(true))]
    })
  }
/// This function implements desugaring for chained inequalities.
This function implements desugaring for chained inequalities.
This function implements desugaring for chained inequalities .
fn build_ineq(&mut self, sp: &FileSpan, args: Vec<LispVal>, op: Binop) -> Result<ast::ExprKind> {
    // Haskell pseudocode:
    // build_ineq [] = error
    // build_ineq [e1] = { e1; true }
    // build_ineq [e1, e2] = e1 < e2
    // build_ineq (e1:e2:e3:es) = { let v1 = e1; let v2 = e2; mk_and v1 v2 e3 es }
    // mk_and v0 v1 e2 es = (v0 < v1 && mk_block v1 e2 es)
    // mk_block v1 e2 [] = (v1 < e2)
    // mk_block v1 e2 (e3:es) = { let v2 = e2; mk_and v1 v2 e3 es }
    macro_rules! sp {($sp:expr, $k:expr) => {Spanned {span: $sp.clone(), k: $k}}}
    macro_rules! binop {($sp:expr, $op:expr, $e1:expr, $e2:expr) => {
      sp!($sp, ast::ExprKind::binop($sp, $op, $e1, $e2))
    }}
    macro_rules! block {($($e:expr),*; $last:expr) => {
      ast::ExprKind::Block(ast::Block {stmts: vec![$($e),*], expr: Some(Box::new($last))})
    }}
    fn binop(sp: &FileSpan, op: Binop, v1: VarId, e2: ast::Expr) -> ast::Expr {
      binop!(sp, op, sp!(sp, ast::ExprKind::Var(v1)), e2)
    }
    fn and(sp: &FileSpan, op: Binop, v1: VarId, v2: VarId, e: ast::Expr) -> ast::Expr {
      binop!(sp, Binop::And, binop(sp, op, v1, sp!(sp, ast::ExprKind::Var(v2))), e)
    }
    let mut it = args.into_iter();
    let arg_1 = it.next().ok_or_else(|| ElabError::new_e(sp, "inequality: syntax error"))?;
    let arg_1 = self.build_expr(sp, arg_1)?;
    Ok(if let Some(arg_2) = it.next() {
      let arg_2 = self.build_expr(sp, arg_2)?;
      if let Some(arg_3) = it.next() {
        fn mk_and(this: &mut BuildAst<'_>, sp: &FileSpan, op: Binop, v0: VarId, v1: VarId, e2: LispVal,
          mut it: std::vec::IntoIter<LispVal>
        ) -> Result<ast::Expr> {
          let e2 = this.build_expr(sp, e2)?;
          Ok(and(sp, op, v0, v1, if let Some(e3) = it.next() {
            let v2 = this.fresh_var(AtomId::UNDER);
            sp!(sp, block![
              let_var(sp, AtomId::UNDER, v2, e2);
              mk_and(this, sp, op, v1, v2, e3, it)?
            ])
          } else {
            binop(sp, op, v1, e2)
          }))
        }
        let v_1 = self.fresh_var(AtomId::UNDER);
        let v_2 = self.fresh_var(AtomId::UNDER);
        block![
          let_var(sp, AtomId::UNDER, v_1, arg_1),
          let_var(sp, AtomId::UNDER, v_2, arg_2);
          mk_and(self, sp, op, v_1, v_2, arg_3, it)?
        ]
      } else {
        ast::ExprKind::binop(sp, op, arg_1, arg_2)
      }
    } else {
      block![arg_1.map_into(ast::StmtKind::Expr); sp!(sp, ast::ExprKind::Bool(true))]
    })
  }
fn build_ineq ( & mut self , sp : & FileSpan , args : Vec < LispVal > , op : Binop ) -> Result < ast :: ExprKind > { // Haskell pseudocode: // build_ineq [] = error // build_ineq [e1] = { e1; true } // build_ineq [e1, e2] = e1 < e2 // build_ineq (e1:e2:e3:es) = { let v1 = e1; let v2 = e2; mk_and v1 v2 e3 es } // mk_and v0 v1 e2 es = (v0 < v1 && mk_block v1 e2 es) // mk_block v1 e2 [] = (v1 < e2) // mk_block v1 e2 (e3:es) = { let v2 = e2; mk_and v1 v2 e3 es } macro_rules! sp { ( $sp : expr $k : expr ) => { Spanned { span $sp clone ( ) k $k } } } macro_rules! binop { ( $sp : expr $op : expr $e1 : expr $e2 : expr ) => { sp ( $sp ast ExprKind binop ( $sp $op $e1 $e2 ) ) } } macro_rules! block { ( $ ( $e : expr ) * $last : expr ) => { ast ExprKind Block ( ast Block { stmts vec [ $ ( $e ) * ] expr Some ( Box new ( $last ) ) } ) } } fn binop ( sp : & FileSpan , op : Binop , v1 : VarId , e2 : ast :: Expr ) -> ast :: Expr { binop ! ( sp op sp ( sp ast ExprKind Var ( v1 ) ) e2 ) } fn and ( sp : & FileSpan , op : Binop , v1 : VarId , v2 : VarId , e : ast :: Expr ) -> ast :: Expr { binop ! ( sp Binop And binop ( sp op v1 sp ( sp ast ExprKind Var ( v2 ) ) ) e ) } let mut it = args . into_iter ( ) ; let arg_1 = it . next ( ) . ok_or_else ( | | ElabError :: new_e ( sp , " " ) ) ? ; let arg_1 = self . build_expr ( sp , arg_1 ) ? ; Ok ( if let Some ( arg_2 ) = it . next ( ) { let arg_2 = self . build_expr ( sp , arg_2 ) ? ; if let Some ( arg_3 ) = it . next ( ) { fn mk_and ( this : & mut BuildAst < ' _ > , sp : & FileSpan , op : Binop , v0 : VarId , v1 : VarId , e2 : LispVal , mut it : std :: vec :: IntoIter < LispVal > ) -> Result < ast :: Expr > { let e2 = this . build_expr ( sp , e2 ) ? ; Ok ( and ( sp , op , v0 , v1 , if let Some ( e3 ) = it . next ( ) { let v2 = this . fresh_var ( AtomId :: UNDER ) ; sp ! ( sp block [ let_var ( sp AtomId UNDER v2 e2 ) mk_and ( this sp op v1 v2 e3 it ) ] ) } else { binop ( sp , op , v1 , e2 ) } ) ) } let v_1 = self . fresh_var ( AtomId :: UNDER ) ; let v_2 = self . fresh_var ( AtomId :: UNDER ) ; block ! [ let_var ( sp AtomId UNDER v_1 arg_1 ) let_var ( sp AtomId UNDER v_2 arg_2 ) mk_and ( self sp op v_1 v_2 arg_3 it ) ] } else { ast :: ExprKind :: binop ( sp , op , arg_1 , arg_2 ) } } else { block ! [ arg_1 map_into ( ast StmtKind Expr ) sp ( sp ast ExprKind Bool ( true ) ) ] } ) }
This function implements desugaring for chained inequalities.
This function implements desugaring for chained inequalities .
&mut self
sp
&FileSpan
args
Vec<LispVal>
op
Binop
&mut self
sp
&FileSpan
args
Vec<LispVal>
op
Binop