Qcert.NRAEnv.Typing.TcNRAEnvInfer


Section TcNRAEnvInfer.




Type inference for NRA when given the type of the input



  Context {m:basic_model}.
  Context (τconstants:list (string×rtype)).

  Fixpoint infer_cnraenv_type (e:cnraenv) (τenv τin:rtype) : option rtype :=
    match e with
      | ANID ⇒ Some τin
      | ANConst d ⇒ infer_data_type (normalize_data brand_relation_brands d)
      | ANBinop b op1 op2 ⇒
        let binf (τ₁ τ₂:rtype) := infer_binop_type b τ₁ τ₂ in
        olift2 binf (infer_cnraenv_type op1 τenv τin) (infer_cnraenv_type op2 τenv τin)
      | ANUnop u op1 ⇒
        let unf (τ₁:rtype) := infer_unop_type u τ₁ in
        olift unf (infer_cnraenv_type op1 τenv τin)
      | ANMap op1 op2 ⇒
        let mapf (τ₁:rtype) :=
            olift (fun x ⇒ lift (fun y ⇒ Coll y) (infer_cnraenv_type op1 τenv x)) (tuncoll τ₁)
        in
        olift mapf (infer_cnraenv_type op2 τenv τin)
      | ANMapConcat op1 op2 ⇒
        let mapconcatf (τ₁:list (string×rtype)) :=
            match RecMaybe Closed τ₁ with
              | None ⇒ None
              | Some τr₁ ⇒
                match olift (tmapConcatOutput τ₁) (infer_cnraenv_type op1 τenv τr₁) with
                  | None ⇒ None
                  | Some τ₂ ⇒ Some (Coll τ₂)
                end
            end
        in
        olift mapconcatf (olift tmapConcatInput (infer_cnraenv_type op2 τenv τin))
      | ANProduct op1 op2 ⇒
        let mapconcatf (τ₁:list (string×rtype)) :=
            match RecMaybe Closed τ₁ with
              | None ⇒ None
              | Some τr₁ ⇒
                match olift (tmapConcatOutput τ₁) (infer_cnraenv_type op2 τenv τin) with
                  | None ⇒ None
                  | Some τ₂ ⇒ Some (Coll τ₂)
                end
            end
        in
        olift mapconcatf (olift tmapConcatInput (infer_cnraenv_type op1 τenv τin))
      | ANSelect op1 op2 ⇒
        let selectf (τ₁:rtype) :=
            match tuncoll τ₁ with
              | Some τ₁' ⇒
                match infer_cnraenv_type op1 τenv τ₁' with
                  | Some τ₂ ⇒
                    match `τ₂ with
                      | Bool₀ ⇒ Some (Coll τ₁')
                      | _ ⇒ None
                    end
                  | None ⇒ None
                end
              | None ⇒ None
            end
        in
        olift selectf (infer_cnraenv_type op2 τenv τin)
      | ANDefault op1 op2 ⇒
        match ((infer_cnraenv_type op1 τenv τin), (infer_cnraenv_type op2 τenv τin)) with
            | (Some τ₁', Some τ₂') ⇒
              match (tuncoll τ₁', tuncoll τ₂') with
                | (Some τ₁₀, Some τ₂₀) ⇒
                  if (`τ₁₀ == `τ₂₀) then Some τ₁' else None
                | _ ⇒ None
              end
            | (_, _) ⇒ None
        end
      | ANEither op1 op2 ⇒
        match tuneither τin with
        | Some (τl, τr) ⇒
          match ((infer_cnraenv_type op1 τenv τl), (infer_cnraenv_type op2 τenv τr)) with
          | (Some τ₁', Some τ₂') ⇒
            if (rtype_eq_dec τ₁' τ₂')
            then Some τ₁'
            else None
          | (_, _) ⇒ None
          end
        | _ ⇒ None
        end
      | ANEitherConcat op1 op2 ⇒
        match (infer_cnraenv_type op1 τenv τin, infer_cnraenv_type op2 τenv τin) with
        | (Some τeither, Some τrecplus) ⇒
          match tuneither τeither with
          | Some (τl, τr) ⇒
            match (trecConcat τl τrecplus, trecConcat τr τrecplus) with
            | (Some τrecl, Some τrecr) ⇒
              Some (Either τrecl τrecr)
            | (_, _) ⇒ None
            end
          | None ⇒ None
          end
        | (_, _) ⇒ None
        end
      | ANApp op1 op2 ⇒
        let appf (τ₁:rtype) := infer_cnraenv_type op1 τenv τ₁ in
        olift appf (infer_cnraenv_type op2 τenv τin)
      | ANGetConstant s ⇒
        tdot τconstants s
      | ANEnv ⇒
        Some τenv
      | ANAppEnv op1 op2 ⇒
        let appf (τ₁:rtype) := infer_cnraenv_type op1 τ₁ τin in
        olift appf (infer_cnraenv_type op2 τenv τin)
      | ANMapEnv op1 ⇒
        let mapf (τenv':rtype) :=
            lift Coll (infer_cnraenv_type op1 τenv' τin)
        in
        olift mapf (tuncoll τenv)
    end.

  Lemma infer_cnraenv_type_correct (τenv τin τout:rtype) (e:cnraenv) :
    infer_cnraenv_type e τenv τin = Some τout →
    cnraenv_type τconstants e τenv τin τout.


End TcNRAEnvInfer.