Module Qcert.Translation.Model.TypeToJSON


Require Import List.
Require Import String.
Require Import ZArith.
Require Import Utils.
Require Import JSON.
Require Import BrandRelation.
Require Import RType.
Require Import RTypeNorm.
Require Import ForeignType.
Require Import ForeignTypeToJSON.

Section TypeToJSON.

  Fixpoint json_brands (d:list json) : option (list string) :=
    match d with
    | nil => Some nil
    | (jstring s1) :: d' =>
      match json_brands d' with
      | Some s' => Some (s1::s')
      | None => None
      end
    | _ => None
    end.

  Context {ftype:foreign_type}.
  Context {ftypeToJSON:foreign_type_to_JSON}.

  Section toRType.
    Fixpoint json_to_rtype₀ (j:json) : rtype₀ :=
      match j with
      | jnull => Unit
      | jnumber _ => Unit
      | jbool _ => Unit
      | jarray _ => Unit
      | jstring "Top" => Top
      | jstring "Bottom" => Bottom
      | jstring "String" => String
      | jstring "Nat" => Nat
      | jstring "Float" => Float
      | jstring "Bool" => Bool
      | jstring _ => Unit
      | jobject nil => RecOpen nil
      | jobject (("$brand"%string,jarray jl)::nil) =>
        match json_brands jl with
        | Some brs => Brandbrs
        | None => Unit
        end
      | jobject (("$coll"%string,j')::nil) => Coll₀ (json_to_rtypej')
      | jobject (("$option"%string,j')::nil) => Either₀ (json_to_rtypej') Unit
      | jobject jl => RecOpen (map (fun kj => ((fst kj), (json_to_rtype₀ (snd kj)))) jl)
      end.

    Definition json_to_rtype {br:brand_relation} (j:json) :=
      normalize_rtype_to_rtype (json_to_rtypej).

    Fixpoint json_to_rtype_with_fail (j:json) : option rtype₀ :=
      match j with
      | jnull => Some Unit
      | jnumber _ => None
      | jbool _ => None
      | jarray _ => None
      | jstring "Top" => Some Top
      | jstring "Bottom" => Some Bottom
      | jstring "String" => Some String
      | jstring "Nat" => Some Nat
      | jstring "Float" => Some Float
      | jstring "Bool" => Some Bool
      | jstring s => lift Foreign₀ (foreign_to_string_to_type s)
      | jobject nil => Some (RecOpen nil)
      | jobject (("$brand"%string,jarray jl)::nil) =>
        match json_brands jl with
        | Some brs => Some (Brandbrs)
        | None => None
        end
      | jobject (("$coll"%string,j')::nil) => lift Coll₀ (json_to_rtype_with_fail j')
      | jobject (("$option"%string,j')::nil) => lift (fun x => Eitherx Unit₀) (json_to_rtype_with_fail j')
      | jobject jl =>
        lift (fun x => RecOpen x)
             ((fix rmap_rec (l: list (string * json)) : option (list (string * rtype₀)) :=
                 match l with
                 | nil => Some nil
                 | (x,y)::l' =>
                   match rmap_rec l' with
                   | None => None
                   | Some l'' =>
                     match json_to_rtype_with_fail y with
                     | None => None
                     | Some y'' => Some ((x,y'') :: l'')
                     end
                   end
                 end) jl)
      end.

    Definition json_to_rtype_with_fail {br:brand_relation} (j:json) : option rtype :=
      lift normalize_rtype_to_rtype (json_to_rtype_with_fail j).

  End toRType.

  Section toVType.
    Definition json_to_vrtype_with_fail {br:brand_relation} (j:json) : option (string * rtype) :=
      match j with
      | jobject (("dist"%string,jstring s)::("type"%string,j')::nil) =>
        lift (fun x => (s,x)) (json_to_rtype_with_fail j')
      | jobject (("type"%string,j')::("dist"%string,jstring s)::nil) =>
        lift (fun x => (s,x)) (json_to_rtype_with_fail j')
      | _ => None
      end.

  End toVType.
End TypeToJSON.