|
| 1 | +open Pretty |
| 2 | +open Cil |
| 3 | +open Feature |
| 4 | +module E = Errormsg |
| 5 | +module H = Hashtbl |
| 6 | + |
| 7 | +let typtbl = H.create 117 |
| 8 | + |
| 9 | +let _ = |
| 10 | + H.add typtbl "int" "int"; |
| 11 | + H.add typtbl "void" "unit"; |
| 12 | + H.add typtbl "float" "double"; |
| 13 | + H.add typtbl "ptr" "MLton.Pointer.t" |
| 14 | + |
| 15 | +type varinfo = {mltyp : string; args : string} |
| 16 | + |
| 17 | +let vartbl = H.create 1009 |
| 18 | + |
| 19 | +let mkFunTy (argTy,resTy) = argTy ^ " -> " ^ resTy |
| 20 | + |
| 21 | +let mkTupleTy tys = "("^(match tys with |
| 22 | + | [] -> "" |
| 23 | + | x::xs -> List.fold_left (fun acc ty -> |
| 24 | + acc^" * "^ty) x xs)^")" |
| 25 | + |
| 26 | +let rec maptype typ = match typ with |
| 27 | + | TVoid _ -> H.find typtbl "void" |
| 28 | + | TInt _ -> H.find typtbl "int" |
| 29 | + | TFloat _ -> H.find typtbl "float" |
| 30 | + | TPtr _ -> H.find typtbl "ptr" |
| 31 | + | TArray _ -> H.find typtbl "ptr" |
| 32 | + | TFun (retTy,None,_,_) -> mkFunTy (H.find typtbl "void",maptype retTy) |
| 33 | + | TFun (retTy,Some argTys,_,_) -> mkFunTy (mkTupleTy |
| 34 | + (List.map (fun (_,ty,_) -> maptype ty) argTys), maptype retTy) |
| 35 | + | TNamed ({tname=tname;ttype=ttype},_) -> (try H.find typtbl tname with |
| 36 | + | Not_found -> |
| 37 | + let mltyname = match Str.string_match (Str.regexp "^Z3_") |
| 38 | + tname 0 with |
| 39 | + | false -> "Tunknown_"^tname |
| 40 | + | true -> "z3_"^(Str.string_after tname 3) in |
| 41 | + (H.add typtbl tname mltyname; |
| 42 | + mltyname)) |
| 43 | + | TComp _ | TEnum _ | TBuiltin_va_list _ -> |
| 44 | + (E.log "Unknown type : %a\n" d_type typ; "Tunknown") |
| 45 | + |
| 46 | +let mapargs typ = match typ with |
| 47 | + | TFun (_,None,_,_) -> "()" |
| 48 | + | TFun (_,Some argTys,_,_) -> "("^(match argTys with |
| 49 | + [] -> "" |
| 50 | + | (x,_,_)::xs -> List.fold_left (fun acc (a,b,c) -> |
| 51 | + acc^","^a) x xs)^")" |
| 52 | + |
| 53 | +let globalFolder x glob = match glob with |
| 54 | + | GVarDecl ({vname=vname;vtype=vtype},_) -> |
| 55 | + let case = Str.string_match (Str.regexp "^Z3_") vname 0 in |
| 56 | + (match case with |
| 57 | + | true -> H.add vartbl vname {mltyp = maptype vtype; |
| 58 | + args = mapargs vtype} |
| 59 | + | false -> ()) |
| 60 | + | _ -> () |
| 61 | + |
| 62 | +let myconcat docs = List.fold_left concat nil docs |
| 63 | + |
| 64 | +let info = "(*\n * Automatically generated by makesml CIL plugin\n *)\n" |
| 65 | + |
| 66 | +let instantiateFunDec (name,args,typ) = |
| 67 | + let decs = myconcat [ |
| 68 | + text ("val dyn_"^name^" = _import * : DynLink.fptr -> " |
| 69 | + ^typ^";"); |
| 70 | + line; |
| 71 | + text ("val "^name^"_ptr = DynLink.dlsym(hndl, \""^name^"\")"); |
| 72 | + ] in |
| 73 | + let expr = text ("dyn_"^name^" "^name^"_ptr "^args) in |
| 74 | + myconcat [ |
| 75 | + text ("fun "^name^" "^args^" = "); |
| 76 | + line; |
| 77 | + text "let"; |
| 78 | + line; |
| 79 | + indent 2 decs; |
| 80 | + line; |
| 81 | + text "in"; |
| 82 | + line; |
| 83 | + indent 2 expr; |
| 84 | + line; |
| 85 | + text "end"; |
| 86 | + line; |
| 87 | + ] |
| 88 | + |
| 89 | +let makeStructDoc () = |
| 90 | + let header = myconcat [text "structure Z3_FFI : Z3_FFI_INTERFACE ="; |
| 91 | + line; text "struct"; line] in |
| 92 | + let typedecs = H.fold (fun _ mlTy doc -> |
| 93 | + if Str.string_match (Str.regexp "^z3_") mlTy 0 |
| 94 | + then myconcat [text ("type "^mlTy^" = MLton.Pointer.t"); |
| 95 | + line; doc] |
| 96 | + else doc) typtbl nil in |
| 97 | + let fundecs = H.fold (fun name {mltyp=typ;args=args} doc -> |
| 98 | + myconcat [doc;line;instantiateFunDec (name,args,typ)]) |
| 99 | + vartbl nil in |
| 100 | + let decs = myconcat [typedecs; line; fundecs] in |
| 101 | + let footer = text "end" in |
| 102 | + let doc = myconcat [header; indent 2 decs; footer] in |
| 103 | + let outf = open_out "z3_ffi.sml" in |
| 104 | + output_string outf info; |
| 105 | + output_string outf (sprint 70 doc) |
| 106 | + (*E.log "%s\n" (sprint 80 doc)*) |
| 107 | + |
| 108 | +let makeSigDoc () = |
| 109 | + let header = concat (concat (concat (text "signature Z3_FFI_INTERFACE =") |
| 110 | + line) (text "sig")) line in |
| 111 | + let typedecs = H.fold (fun _ mlTy doc -> |
| 112 | + if Str.string_match (Str.regexp "^z3_") mlTy 0 |
| 113 | + then concat (concat (text ("type "^mlTy)) line) doc |
| 114 | + else doc) typtbl nil in |
| 115 | + let vardecs = H.fold (fun vname {mltyp=mlTy;} doc -> myconcat |
| 116 | + [text ("val "^vname^" : "^mlTy);line;doc]) vartbl nil in |
| 117 | + let decs = myconcat [typedecs;line;vardecs] in |
| 118 | + let footer = text "end" in |
| 119 | + let doc = concat (concat header (indent 2 decs)) footer in |
| 120 | + let outf = open_out "z3_ffi.sig" in |
| 121 | + output_string outf info; |
| 122 | + output_string outf (sprint 70 doc) |
| 123 | + (*E.log "%s\n" (sprint 80 doc)*) |
| 124 | + |
| 125 | +let featureHook (f : file) = |
| 126 | + let _ = foldGlobals f globalFolder () in |
| 127 | + let sigdoc = makeSigDoc () in |
| 128 | + let structdoc = makeStructDoc () in |
| 129 | + () |
| 130 | + |
| 131 | +let feature = |
| 132 | + { fd_name = "makesml"; |
| 133 | + fd_enabled = false; |
| 134 | + fd_description = "Convert z3_api.h to Z3_FFI.sml"; |
| 135 | + fd_extraopt = []; |
| 136 | + fd_doit = featureHook; |
| 137 | + fd_post_check = false; |
| 138 | + } |
| 139 | +let _ = E.log "makesml feature registered\n" |
| 140 | +let () = Feature.register feature |
0 commit comments