Skip to content

Instantly share code, notes, and snippets.

@edwintorok
Last active August 23, 2020 20:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edwintorok/de35147a1c35a8ab0799e3ab3247b466 to your computer and use it in GitHub Desktop.
Save edwintorok/de35147a1c35a8ab0799e3ab3247b466 to your computer and use it in GitHub Desktop.
ocaml code generator
let prologue =
{|
(* This code is automatically generated *)
let string_of_string x = x
|}
let epilogue =
{|
let print t = pp Format.std_formatter t
let () =
Csv.Rows.load ~has_header:true "datainput.csv"
|> List.map decode
|> List.iter print
|}
let map_hstype = function
| "String" ->
"string"
| "Int" ->
"int"
| "DayOfWeek" ->
"string" (* for now *)
| t ->
failwith ("Unknown type: " ^ t)
let () =
let inpath = Sys.argv.(1) in
Stdio.Out_channel.with_file Sys.argv.(2) ~f:(fun out ->
let print s = Printf.fprintf out "%s\n" s in
print prologue ;
let schema =
Csv.Rows.load ~has_header:true inpath
|> List.map Csv.Row.to_list
|> List.mapi (fun i -> function
| [field; typ; _parser] ->
let i = i + 2 in
let field = String.lowercase_ascii field in
(i, field, map_hstype typ)
| line ->
failwith ("Unknown line format: " ^ String.concat "," line))
in
print {|type t = { |} ;
List.iter
(fun (i, f, t) ->
Printf.sprintf {|# %d "%s"|} i inpath |> print ;
let sep = if i > 2 then "; " else "" in
Printf.sprintf "%s%s: %s\n" sep f t |> print)
schema ;
print {| } |} ;
print {|let decode row = |} ;
List.iteri
(fun j (_i, f, t) ->
Printf.sprintf {|let %s = Csv.Row.get row %d |> %s_of_string in|} f j
t
|> print)
schema ;
print {|{|} ;
schema
|> List.map (fun (_, f, _) -> f)
|> String.concat "; " |> print ;
print {| }|} ;
print {|let pp = Fmt.Dump.record [|} ;
List.iter
(fun (_, f, t) ->
Printf.sprintf "Fmt.Dump.field \"%s\" (fun t -> t.%s) Fmt.%s;\n" f f t
|> print)
schema ;
print {| ]|} ;
print epilogue)
Name Age Date
Name 1 20 Monday
Another Name 30 Tuesday
(executable
(name codegen)
(modules codegen)
(libraries stdio csv)
)
(rule
(target generated.ml)
(deps input.csv)
(action (run %{exe:codegen.exe} %{deps} %{target}))
)
(tests
(deps datainput.csv)
(names generated)
(modules generated)
(libraries fmt csv)
)
Field Type Parser
Name String id
Age Int readEither
Date DayOfWeek readEither
@edwintorok
Copy link
Author

dune runtest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment