1 (* C++ code generation *)
12 type value = string * string
16 String.concat
", " (List.map
(fun (n
,t
) -> t ^
" " ^ n
) x
)
19 String.concat
", " (List.map
(fun (n
,t
) -> n
) x
)
21 let quote = String.replace_chars
(function '
\n'
-> "\\\n" | '
\r'
-> "" | '
"' -> "\\\"" | c -> String.make 1 c)
22 let quote s = "\"" ^ quote s ^ "\""
25 let (inc_indent,dec_indent,make_indent) =
27 (fun () -> v := !v + 2),
28 (fun () -> v := !v - 2),
29 (fun () -> String.make !v ' ')
31 let print_indent () = print_string (make_indent ())
32 let indent s = print_indent (); print_string s
33 let indent_endline s = print_indent (); print_endline s
34 let empty_line () = print_newline ()
35 let output fmt = Printf.kprintf indent_endline fmt
36 let print fmt = Printf.kprintf print_endline fmt
37 let quote_comment_inline = String.replace_chars (function '\n' -> "\n// " | c -> String.make 1 c)
38 let comment fmt = Printf.kprintf (indent_endline & quote_comment_inline & (^) "// ") fmt
39 let open_curly () = output "{"; inc_indent ()
40 let close_curly fmt = dec_indent (); indent "}"; print fmt
41 let start_struct name =
42 output "struct %s
" name;
45 close_curly "; // struct %s
" name;
47 let out_public () = dec_indent(); output "public
:"; inc_indent()
48 let out_private () = dec_indent(); output "private:"; inc_indent()
49 let in_namespace name f =
50 output "namespace %s
" name;
53 close_curly " // namespace %s
" name;
57 let generate_header () =
58 output "// DO NOT EDIT MANUALLY
";
60 output "// generated by sqlgg %s
" Config.version;
62 output "#pragma once
";
65 let name_of attr index =
66 match attr.RA.name with
67 | "" -> sprintf "_%u
" index
70 let set_column attr index =
71 output "Traits
::set_column_%s
(stmt
, %u
, obj
.%s
);"
72 (Type.to_string attr.RA.domain)
76 let get_column attr index =
77 output "Traits
::get_column_%s
(stmt
, %u
, obj
.%s
);"
78 (Type.to_string attr.RA.domain)
80 (name_of attr (index+1))
82 let param_type_to_string t = Option.map_default Type.to_string "Any
" t
83 let param_type_to_cpp_string t = "typename Traits
::" ^ (param_type_to_string t)
85 let param_name_to_string id index =
87 | Next -> sprintf "_%u
" index
88 | Numbered x -> sprintf "_%u
" x
91 let make_name props default = Option.default default (Props.get props "name
")
92 let default_name str index = sprintf "%s_%u
" str index
94 let set_param index param =
96 output "Traits
::set_param_%s
(stmt
, %s
, %u
);"
97 (param_type_to_string t)
98 (param_name_to_string id index)
101 let output_scheme_binder index scheme =
103 let name = default_name "output" index in
104 output "template
<class T
>";
107 output "static void of_stmt
(typename Traits
::statement stmt
, T
& obj
)";
109 List.iteri (fun index attr -> get_column attr index) scheme;
115 let output_scheme_binder index scheme =
118 | _ -> Some (output_scheme_binder index scheme)
120 let params_to_values = List.mapi (fun i (n,t) -> param_name_to_string n i, param_type_to_cpp_string t)
121 let params_to_values = List.unique & params_to_values
122 let make_const_values = List.map (fun (name,t) -> name, sprintf "%s const
&" t)
124 let output_value_defs vals =
125 vals >> List.iter (fun (name,t) -> output "%s %s
;" t name)
127 let scheme_to_values = List.mapi (fun i attr -> name_of attr i, Type.to_cpp_string attr.RA.domain)
129 let output_scheme_data index scheme =
131 let name = default_name "data
" index in
133 scheme >> scheme_to_values >> output_value_defs;
136 let output_value_inits vals =
141 (String.concat "," (List.map (fun (name,_) -> sprintf "%s
(%s
)" name name) vals))
143 let output_params_binder index params =
145 let name = default_name "params
" index in
147 let values = params_to_values params in
148 values >> make_const_values >> output_value_defs;
150 output "%s
(%s
)" name (values >> make_const_values >> Cpp.to_string);
151 output_value_inits values;
155 output "void set_params
(typename Traits
::statement stmt
)";
157 List.iteri set_param params;
163 let output_params_binder index params =
165 | [] -> "typename Traits
::no_params
"
166 | _ -> output_params_binder index params
168 let choose_name props kind index =
169 (* let name = default_name (Show.show<Stmt.Raw.kind>(kind) >> String.lowercase) index in *)
170 let name = match kind with
171 | Create t -> sprintf "create_%s
" t
172 | Update t -> sprintf "update_%s_%u
" t index
173 | Insert t -> sprintf "insert_%s_%u
" t index
174 | Delete t -> sprintf "delete_%s_%u
" t index
175 | Select -> sprintf "select_%u
" index
179 let generate_code index scheme params kind props =
180 let scheme_binder_name = output_scheme_binder index scheme in
181 let params_binder_name = output_params_binder index params in
182 if (Option.is_some scheme_binder_name) then output_scheme_data index scheme;
184 if (Option.is_some scheme_binder_name) then output "template
<class T
>";
185 let values = params_to_values params in
186 let result = match scheme_binder_name with None -> [] | Some _ -> ["result","T
&"] in
187 let all_params = Cpp.to_string
188 (["db
","typename Traits
::connection
"] @ result @ (make_const_values values))
190 let name = choose_name props kind index in
191 let sql = Props.get props "sql" >> Option.get in
193 let sql = match kind with
194 | Insert _ -> sql ^ " (" ^ (String.concat "," (List.map (fun _ -> "?
") params)) ^ ")"
195 | Select | Update _ | Delete _ | Create _ -> sql
197 let sql = Cpp.quote sql in
198 let inline_params = Cpp.inline (make_const_values values) in
199 output "static
bool %s
(%s
)" name all_params;
201 begin match scheme_binder_name with
202 | None -> output "return Traits
::do_execute
(db
,_T
(%s
),%s
(%s
));" sql params_binder_name inline_params
203 | Some scheme_name ->output "return Traits
::do_select
(db
,result,_T
(%s
),%s
(),%s
(%s
));"
204 sql (scheme_name ^ "<typename T
::value_type
>") params_binder_name inline_params
209 let generate_code index stmt =
210 let ((scheme,params,kind),props) = stmt in
211 begin match Props.get props "sql" with
212 | Some s -> comment "%s
" s
215 generate_code index scheme params kind props
219 output "template
<class Traits
>";
220 start_struct "sqlgg
";
221 List.iteri generate_code stmts;