Module Qcert.Translation.Lang.NNRCtoJava
Require Import List.
Require Import String.
Require Import BinInt.
Require Import Ascii.
Require Import Peano_dec.
Require Import EquivDec.
Require Import Utils.
Require Import DataRuntime.
Require Import JavaRuntime.
Require Import NNRCRuntime.
Require Import ForeignToJava.
Import ListNotations.
Local Open Scope string_scope.
Section NNRCtoJava.
  
Section sanitizer.
    
Definition unshadow_java {
fruntime:
foreign_runtime} (
avoid:
list var) (
e:
nnrc) : 
nnrc
      := 
unshadow javaSafeSeparator javaIdentifierSanitize (
avoid++
javaAvoidList) 
e.
    
Definition javaSanitizeNNRC {
fruntime:
foreign_runtime} (
e:
nnrc) : 
nnrc
      := 
unshadow_java nil e.
  
End sanitizer.
  
Context {
fruntime:
foreign_runtime}.
  
Section DataJava.
    
Context {
ftojavajson:
foreign_to_java}.
    
Definition mk_java_json_brands (
quotel:
string) (
b:
brands) : 
java_json
      := 
mk_java_json_array (
map (
mk_java_json_string quotel) 
b).
    
Fixpoint mk_java_json_data (
quotel:
string) (
d : 
data) : 
java_json :=
      
match d with
      | 
dunit => 
java_json_NULL
      | 
dnat n => 
mk_java_json_nat quotel n
      | 
dfloat n => 
mk_java_json_number n
      | 
dbool b => 
mk_java_json_bool b
      | 
dstring s => 
mk_java_json_string quotel s
      | 
dcoll ls => 
mk_java_json_array (
map (
mk_java_json_data quotel) 
ls)
      | 
drec ls => 
mk_java_json_object
                     quotel
                     (
map (
fun kv =>
                             
let '(
k,
v) := 
kv in
                             (
k, (
mk_java_json_data quotel v))) 
ls)
      | 
dleft d => 
mk_java_json_object quotel
                                       [("$
left", (
mk_java_json_data quotel d))]
                                       
      | 
dright d => 
mk_java_json_object quotel
                                        [("$
right", (
mk_java_json_data quotel d))]
                                        
      | 
dbrand b d =>
        
mk_java_json_object quotel
                            [("$
data", 
mk_java_json_data quotel d)
                             ; ("$
type", 
mk_java_json_brands quotel b)]
      | 
dforeign fd => 
foreign_to_java_data quotel fd
      end.
  
End DataJava.
  
Section test.
    
Import ListNotations.
    
    
Definition testd
      := 
drec (
rec_sort [
                   ("
hi", 
dcoll [
dnat 3; 
dnat 4])
                   ; ("
there", 
dbool false)
                   ; ("
is", 
dstring "
hi")
                   ; ("
b", 
dbrand ["
C1"; "
I1"; "
C2"]
                                  (
dcoll [
dbool true; 
dbool false]))]).
    
Context {
ftojavajson:
foreign_to_java}.
    
    
  
End test.
  
Section NNRCJava.
    
Context {
ftojavajson:
foreign_to_java}.
    
Import ListNotations.
    
Definition uarithToJavaMethod (
u:
nat_arith_unary_op) :=
      
match u with
      | 
NatAbs => "
abs"
      | 
NatLog2 => "
log2"
      | 
NatSqrt =>"
sqrt"
      
end.
    
Definition float_uarithToJavaMethod (
fu:
float_arith_unary_op) :=
      
match fu with
      | 
FloatNeg => "
float_neg"
      | 
FloatSqrt => "
float_sqrt"
      | 
FloatExp => "
float_exp"
      | 
FloatLog => "
float_log"
      | 
FloatLog10 => "
float_log10"
      | 
FloatCeil => "
float_ceil"
      | 
FloatFloor => "
float_floor"
      | 
FloatAbs => "
float_abs"
      
end.
    
Definition nat_barithToJavaMethod (
b:
nat_arith_binary_op)  :=
      
match b with
      | 
NatPlus => "
plus"
      | 
NatMinus => "
minus "
      | 
NatMult => "
mult"
      | 
NatDiv => "
divide"
      | 
NatRem => "
rem"
      | 
NatMin => "
min"
      | 
NatMax => "
max"
      
end.
    
Definition float_barithToJavaMethod (
fb:
float_arith_binary_op)
      := 
match fb with
         | 
FloatPlus => "
float_plus"
         | 
FloatMinus => "
float_minus"
         | 
FloatMult => "
float_mult"
         | 
FloatDiv => "
float_divide"
         | 
FloatPow => "
float_pow"
         | 
FloatMin => "
float_min"
         | 
FloatMax => "
float_max"
         
end.
    
Definition float_bcompareToJavaMethod (
fb:
float_compare_binary_op)
      := 
match fb with
         | 
FloatLt => "
float_lt"
         | 
FloatLe => "
float_le"
         | 
FloatGt => "
float_gt"
         | 
FloatGe => "
float_ge"
         
end.
    
Definition like_clause_to_java (
lc:
like_clause)
      := 
match lc with
         | 
like_literal literal => "
new UnaryOperators.LiteralLikeClause(" ++ (
mk_java_string literal) ++ ")"
         | 
like_any_char => "
new UnaryOperators.AnyCharLikeClause()"
         | 
like_any_string => "
new UnaryOperators.AnyStringLikeClause()"
         
end.
    
    
Fixpoint nnrcToJava
             (
n : 
nnrc)                      
             (
t : 
nat)                       
             (
i : 
nat)                       
             (
eol : 
string)                 
             (
quotel : 
string)              
             (
ivs : 
list (
string * 
string)) 
      : 
string                              
        * 
java_json                          
        * 
nat                                
      := 
match n with
         | 
NNRCGetConstant v =>
           ("", 
mk_java_json ("
v" ++ 
v), 
t)
         | 
NNRCVar v =>
           
match assoc_lookupr equiv_dec ivs v with
           | 
Some v_string => ("", 
mk_java_json v_string, 
t)
           | 
None => ("", 
mk_java_json ("
v" ++ 
v), 
t)
           
end
         | 
NNRCConst d => ("", (
mk_java_json_data quotel d), 
t)
         | 
NNRCUnop op n1 =>
           
let '(
s1, 
e1, 
t0) := 
nnrcToJava n1 t i eol quotel ivs in
           let e0 := 
match op with
                     | 
OpIdentity => 
e1
                     | 
OpNeg => 
mk_java_unary_op0 "
neg" 
e1
                     | 
OpRec s => 
mk_java_unary_op1 "
rec" (
mk_java_string s) 
e1
                     | 
OpDot s => 
mk_java_unary_op1 "
dot" (
mk_java_string s) 
e1
                     | 
OpRecRemove s => 
mk_java_unary_op1 "
remove"  (
mk_java_string s) 
e1
                     | 
OpRecProject sl => 
mk_java_unary_op1 "
project" (
mk_java_string_collection sl) 
e1
                     | 
OpBag => 
mk_java_unary_op0 "
coll" 
e1
                     | 
OpSingleton => 
mk_java_unary_op0 "
singleton" 
e1
                     | 
OpFlatten => 
mk_java_unary_op0 "
flatten" 
e1
                     | 
OpDistinct => 
mk_java_unary_op0 "
distinct" 
e1
                     | 
OpOrderBy sl =>
                       
mk_java_unary_op1 "
sort" (
mk_java_sort_criterias quotel sl) 
e1
                     | 
OpCount => 
mk_java_unary_op0 "
count" 
e1
                     | 
OpToString =>  
mk_java_unary_op0 "
tostring" 
e1
                     | 
OpToText =>  
mk_java_unary_op0 "
totext" 
e1
                     | 
OpLength =>  
mk_java_unary_op0 "
stringlength" 
e1
                     | 
OpSubstring start olen =>
                       
match olen with
                       | 
Some len => 
mk_java_unary_opn "
substring" (
map toString [
start; 
len]) 
e1
                       | 
None => 
mk_java_unary_op1 "
substring" (
toString start) 
e1
                       end
                     | 
OpLike pat =>
                       
let lc := 
make_like_clause pat None in
                       mk_java_unary_op1 "
string_like" ("
new UnaryOperators.LikeClause[]{"
                                         ++ (
map_concat "," 
like_clause_to_java lc) ++ "}") 
e1
                     | 
OpLeft => 
mk_java_unary_op0 "
left" 
e1
                     | 
OpRight => 
mk_java_unary_op0 "
right" 
e1
                     | 
OpBrand b =>
mk_java_unary_op1 "
brand" (
mk_java_string_collection b) 
e1
                     | 
OpUnbrand => 
mk_java_unary_op0 "
unbrand" 
e1
                     | 
OpCast b => 
mk_java_unary_opn "
cast" ["
inheritance"; (
mk_java_string_collection b)] 
e1
                     | 
OpNatUnary u => 
mk_java_unary_op0 (
uarithToJavaMethod u) 
e1
                     | 
OpNatSum =>  
mk_java_unary_op0 "
sum" 
e1
                     | 
OpNatMin => 
mk_java_unary_op0 "
list_min" 
e1
                     | 
OpNatMax =>  
mk_java_unary_op0 "
list_max" 
e1
                     | 
OpNatMean => 
mk_java_unary_op0 "
list_mean" 
e1
                     | 
OpFloatOfNat => 
mk_java_unary_op0 "
float_of_int" 
e1
                     | 
OpFloatUnary u => 
mk_java_unary_op0 (
float_uarithToJavaMethod u) 
e1
                     | 
OpFloatTruncate => 
mk_java_unary_op0 "
float_truncate" 
e1
                     | 
OpFloatSum =>  
mk_java_unary_op0 "
float_sum" 
e1
                     | 
OpFloatBagMin => 
mk_java_unary_op0 "
float_list_min" 
e1
                     | 
OpFloatBagMax =>  
mk_java_unary_op0 "
float_list_max" 
e1
                     | 
OpFloatMean => 
mk_java_unary_op0 "
float_list_mean" 
e1
                     | 
OpForeignUnary fu
                       => 
foreign_to_java_unary_op i eol quotel fu e1
                     end in
           (
s1, 
e0, 
t0)
         | 
NNRCBinop op n1 n2 =>
           
let '(
s1, 
e1, 
t2) := 
nnrcToJava n1 t i eol quotel ivs in
           let '(
s2, 
e2, 
t0) := 
nnrcToJava n2 t2 i eol quotel ivs in
           let e0 := 
match op with
                     | 
OpEqual => 
mk_java_binary_op0 "
equals" 
e1 e2
                     | 
OpRecConcat => 
mk_java_binary_op0 "
concat" 
e1 e2
                     | 
OpRecMerge => 
mk_java_binary_op0 "
mergeConcat" 
e1 e2
                     | 
OpAnd => 
mk_java_binary_op0 "
and" 
e1 e2
                     | 
OpOr => 
mk_java_binary_op0 "
or" 
e1 e2
                     | 
OpLt =>  
mk_java_binary_op0 "
lt" 
e1 e2
                     | 
OpLe =>  
mk_java_binary_op0 "
le" 
e1 e2
                     | 
OpBagUnion => 
mk_java_binary_op0 "
union" 
e1 e2
                     | 
OpBagDiff =>  
mk_java_binary_op0 "
bag_minus" 
e1 e2
                     | 
OpBagMin =>  
mk_java_binary_op0 "
bag_min" 
e1 e2
                     | 
OpBagMax =>  
mk_java_binary_op0 "
bag_max" 
e1 e2
                     | 
OpBagNth =>  
mk_java_binary_op0 "
bag_nth" 
e1 e2
                     | 
OpContains =>  
mk_java_binary_op0 "
contains" 
e1 e2
                     | 
OpStringConcat => 
mk_java_binary_op0 "
stringConcat" 
e1 e2
                     | 
OpStringJoin => 
mk_java_binary_op0 "
stringJoin" 
e1 e2
                     | 
OpNatBinary b => 
mk_java_binary_op0 (
nat_barithToJavaMethod b) 
e1 e2
                     | 
OpFloatBinary b => 
mk_java_binary_op0 (
float_barithToJavaMethod b) 
e1 e2
                     | 
OpFloatCompare b => 
mk_java_binary_op0 (
float_bcompareToJavaMethod b) 
e1 e2
                     | 
OpForeignBinary fb
                       => 
foreign_to_java_binary_op i eol quotel fb e1 e2
                     end in
           (
s1 ++ 
s2, 
e0, 
t0)
         | 
NNRCLet v bind body =>
           
let '(
s1, 
e1, 
t2) := 
nnrcToJava bind t i eol quotel ivs in
           let '(
s2, 
e2, 
t0) := 
nnrcToJava body t2 i eol quotel ivs in
           let v0 := "
v" ++ 
v in
           let ret := "
vletvar$" ++ 
v ++ "$" ++ (
nat_to_string10 t0) 
in
           (
s1
              ++ (
indent i) ++ "
final JsonElement " ++ 
ret ++ ";" ++ 
eol
              ++ (
indent i) ++ "{ // 
new scope introduced for a let statement" ++ 
eol
              ++ (
indent (
i+1)) ++ "
final JsonElement " ++ 
v0 ++ " = " ++ (
from_java_json e1) ++ ";" ++ 
eol
              ++ 
s2
              ++ (
indent (
i+1)) ++ 
ret ++ " = " ++ (
from_java_json e2) ++ ";" ++ 
eol
              ++ (
indent i) ++ "}" ++ 
eol,
            
mk_java_json ret, 
t0+1)
         | 
NNRCFor v iter body =>
           
let '(
s1, 
e1, 
t2) := 
nnrcToJava iter t i eol quotel ivs in
           let '(
s2, 
e2, 
t0) := 
nnrcToJava body t2 (
i+1) 
eol quotel ivs in
           let elm := "
v" ++ 
v in
           let src := "
src" ++ (
nat_to_string10 t0) 
in
           let idx := "
i" ++ (
nat_to_string10 t0) 
in
           let dst := "
dst" ++ (
nat_to_string10 t0) 
in
           (
s1 ++ (
indent i) ++ "
final JsonArray " ++ 
src ++ " = (
JsonArray) " ++ (
from_java_json e1) ++ ";" ++ 
eol
               ++ (
indent i) ++ "
final JsonArray " ++ 
dst ++ " = 
new JsonArray();" ++ 
eol
               ++ (
indent i) ++ "
for(
int " ++ 
idx ++ " = 0; " ++ 
idx ++ " < " ++ 
src ++ ".
size(); " ++ 
idx ++ "++) {" ++ 
eol
               ++ (
indent (
i+1)) ++ "
final JsonElement " ++ 
elm ++ " = " ++ 
src ++ ".
get(" ++ 
idx ++ ");" ++ 
eol
               ++ 
s2
               ++ (
indent (
i+1)) ++ 
dst ++ ".
add(" ++ (
from_java_json e2) ++ ");" ++ 
eol
               ++ (
indent i) ++ "}" ++ 
eol,
            (
mk_java_json dst), 
t0 + 1)
         | 
NNRCIf c n1 n2 =>
           
let '(
s1, 
e1, 
t2) := 
nnrcToJava c t i eol quotel ivs in
           let '(
s2, 
e2, 
t3) := 
nnrcToJava n1 t2 (
i+1) 
eol quotel ivs in
           let '(
s3, 
e3, 
t0) := 
nnrcToJava n2 t3 (
i+1) 
eol quotel ivs in
           let v0 := "
t" ++ (
nat_to_string10 t0) 
in
           (
s1 ++ (
indent i) ++ "
final JsonElement " ++ 
v0 ++ ";" ++ 
eol
               ++ (
indent i) ++ "
if (
RuntimeUtils.asBoolean(" ++ (
from_java_json e1) ++ ")) {" ++ 
eol
               ++ 
s2
               ++ (
indent (
i+1)) ++ 
v0 ++ " = " ++ (
from_java_json e2) ++ ";" ++ 
eol
               ++ (
indent i) ++ "} 
else {" ++ 
eol
               ++ 
s3
               ++ (
indent (
i+1)) ++ 
v0 ++ " = " ++ (
from_java_json e3) ++ ";" ++ 
eol
               ++ (
indent i) ++ "}" ++ 
eol,
            (
mk_java_json v0), 
t0 + 1)
         | 
NNRCEither nd xl nl xr nr =>
           
let '(
s1, 
e1, 
t2) := 
nnrcToJava nd t i eol quotel ivs in
           let '(
s2, 
e2, 
t1) := 
nnrcToJava nl t2 (
i+1) 
eol quotel ivs in
           let '(
s3, 
e3, 
t0) := 
nnrcToJava nr t1 (
i+1) 
eol quotel ivs in
           let vl := "
v" ++ 
xl in
           let vr := "
v" ++ 
xr in
           let res := "
res" ++ (
nat_to_string10 t0) 
in  
           (
s1 ++ (
indent i) ++ "
final JsonElement " ++ 
res ++ ";" ++ 
eol
               ++ (
indent i) ++ "
if (
RuntimeUtils.either(" ++ (
from_java_json e1) ++")) {" ++ 
eol
               ++ (
indent (
i+1)) ++ "
final JsonElement " ++ 
vl ++ 
eol
               ++ (
indent (
i+1)) ++ " = 
RuntimeUtils.getLeft(" ++ (
from_java_json e1) ++ ");" ++ 
eol
               ++ 
s2
               ++ (
indent (
i+1)) ++ 
res ++ " = " ++ (
from_java_json e2) ++ ";" ++ 
eol
               ++ (
indent i) ++ "} 
else {" ++ 
eol
               ++ (
indent (
i+1)) ++ "
final JsonElement " ++ 
vr  ++ 
eol
               ++ (
indent (
i+1)) ++ " = 
RuntimeUtils.getRight(" ++ (
from_java_json e1) ++ ");" ++ 
eol
               ++ 
s3
               ++ (
indent (
i+1)) ++ 
res ++ " = " ++ (
from_java_json e3) ++ ";" ++ 
eol
               ++ (
indent i) ++ "}" ++ 
eol,
            
mk_java_json res, 
t0 + 1)
         | 
NNRCGroupBy g sl n1 =>
           
let '(
s1, 
e1, 
t0) := 
nnrcToJava n1 t i eol quotel ivs in
           let e0 := 
mk_java_unary_opn "
groupby" [(
mk_java_string g);(
mk_java_string_collection sl)] 
e1 in
           (
s1, 
e0, 
t0)
       
end.
    
Definition nnrcToJavaunshadow (
n : 
nnrc) (
t : 
nat) (
i : 
nat) (
eol : 
string) (
quotel : 
string) (
avoid: 
list var) (
ivs : 
list (
string * 
string)) :=
      
let n := 
unshadow_java avoid n in
      nnrcToJava n t i eol quotel ivs.
    
Definition makeJavaParams (
ivs: 
list(
string*
string)) :=
      
map_concat ", " (
fun elem => "
JsonElement " ++ 
snd elem) 
ivs.
    
Definition closeFreeVars (
input:
string) (
e:
nnrc) (
ivs:
list(
string*
string)) : 
nnrc :=
      
let all_free_vars := 
nnrc_global_vars e in
      let wrap_one_free_var (
e':
nnrc) (
fv:
string) : 
nnrc :=
          
if (
assoc_lookupr equiv_dec ivs fv)
          
then e'
          
else
            (
NNRCLet fv (
NNRCUnop (
OpDot fv) (
NNRCVar input)) 
e')
      
in
      fold_left wrap_one_free_var all_free_vars e.
    
    
Definition nnrcToJavaFun (
i:
nat) (
input_v:
string) (
e:
nnrc) (
eol:
string) (
quotel:
string) (
ivs : 
list (
string * 
string)) (
fname:
string) :=
      
let e' := 
closeFreeVars input_v e ivs in
      let '(
j0, 
v0, 
t0) := 
nnrcToJavaunshadow e' 1 (
i + 1) 
eol quotel ("
constants"::"
inheritance"::(
List.map fst ivs)) 
ivs in
      (
indent i) ++ "
public JsonElement " ++ 
fname ++ "(
Inheritance inheritance, " ++ (
makeJavaParams ivs) ++ ") {" ++ 
eol
                 ++ 
j0
                 ++ (
indent i) ++ "  
return " ++ (
from_java_json v0) ++ ";" ++ 
eol
                 ++ (
indent i) ++ "}" ++ 
eol.
    
Definition nnrcToJavaClass (
class_name:
string) (
package_name:
string) (
imports:
string) (
input_v:
string) (
e:
nnrc) (
eol:
string) (
quotel:
string) (
ivs : 
list (
string * 
string)) (
fname:
string) :=
      
let f := 
nnrcToJavaFun 1 
input_v e eol quotel ivs fname in
      (
if(
package_name == "")
      
then ""
      
else "
package " ++ 
package_name ++ ";" ++ 
eol ++ 
eol)
        ++ "
import com.google.gson.*;" ++ 
eol
        ++ (
if(
imports == "")
            
then ""
            
else "
import " ++ 
imports ++ ";" ++ 
eol)
        ++ (
if(
package_name == "
org.qcert.runtime")
            
then ""
            
else "
import org.qcert.runtime.*;" ++ 
eol)
      ++ 
eol
      ++ "
public class " ++ 
class_name ++ " 
implements JavaQuery { " ++ 
eol
      ++ 
f
      ++ "}" ++ 
eol
    .
    
Definition nnrc_to_java_top (
class_name:
string) (
imports:
string) (
e:
nnrc) : 
java :=
      
let input_f := "
query" 
in
      let input_v := "
constants" 
in
      nnrcToJavaClass class_name "" 
imports input_v e eol_newline quotel_double ((
input_v, 
input_v)::
nil) 
input_f.
  
End NNRCJava.
End NNRCtoJava.