pax_global_header00006660000000000000000000000064140115261570014514gustar00rootroot0000000000000052 comment=86f2f05c4605572022cdb794c5542d220fb14be5 cinaps-0.15.1/000077500000000000000000000000001401152615700130555ustar00rootroot00000000000000cinaps-0.15.1/.gitignore000066400000000000000000000000411401152615700150400ustar00rootroot00000000000000_build *.install *.merlin _opam cinaps-0.15.1/CHANGES.md000066400000000000000000000003421401152615700144460ustar00rootroot00000000000000## v0.15.1 ### Changed - The styler is now unconditionally applied; it used to be applied only to files with extension ".ml" or ".mli" (#5) ## v0.15.0 ### Fixed - Make cinaps compatible with ocaml 4.04 (#4, @NathanReb) cinaps-0.15.1/CONTRIBUTING.md000066400000000000000000000044101401152615700153050ustar00rootroot00000000000000This repository contains open source software that is developed and maintained by [Jane Street][js]. Contributions to this project are welcome and should be submitted via GitHub pull requests. Signing contributions --------------------- We require that you sign your contributions. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. The rules are pretty simple: if you can certify the below (from [developercertificate.org][dco]): ``` Developer Certificate of Origin Version 1.1 Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 1 Letterman Drive Suite D4700 San Francisco, CA, 94129 Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. ``` Then you just add a line to every git commit message: ``` Signed-off-by: Joe Smith ``` Use your real name (sorry, no pseudonyms or anonymous contributions.) If you set your `user.name` and `user.email` git configs, you can sign your commit automatically with git commit -s. [dco]: http://developercertificate.org/ [js]: https://opensource.janestreet.com/ cinaps-0.15.1/LICENSE.md000066400000000000000000000021351401152615700144620ustar00rootroot00000000000000The MIT License Copyright (c) 2017--2020 Jane Street Group, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cinaps-0.15.1/Makefile000066400000000000000000000004031401152615700145120ustar00rootroot00000000000000INSTALL_ARGS := $(if $(PREFIX),--prefix $(PREFIX),) default: dune build install: dune install $(INSTALL_ARGS) uninstall: dune uninstall $(INSTALL_ARGS) reinstall: uninstall install clean: dune clean .PHONY: default install uninstall reinstall clean cinaps-0.15.1/README.org000066400000000000000000000105621401152615700145270ustar00rootroot00000000000000* CINAPS - Cinaps Is Not A Preprocessing System Cinaps is a trivial Metaprogramming tool for OCaml using the OCaml toplevel. It is intended for two purposes: - when you want to include a bit of generated code in a file, but writing a proper generator/ppx rewriter is not worth it - when you have many repeated blocks of similar code in your program, to help writing and maintaining them It is not intended as a general preprocessor, and in particular cannot only be used to generate static code that is independent of the system. ** How does it work? Cinaps is a purely textual tool. It recognizes special syntax of the form =(*$ *)= in the input. == is evaluated and whatever it prints on the standard output is compared against what follows in the file until the next =($ ... *)= form, in the same way that expectation tests works. A form ending with =$*)= stops the matching and switch back to plain text mode. In particular the empty form =(*$*)= can be used to mark the end of a generated block. If the actual output doesn't match the expected one, cinaps creates a =.corrected= file containing the actual output, diff the original file against the actual output and exits with an error code. Other it simply exits with error code 0. For instance: #+begin_src sh $ cat file.ml let x = 1 (*$ print_newline (); List.iter (fun s -> Printf.printf "let ( %s ) = Pervasives.( %s )\n" s s) ["+"; "-"; "*"; "/"] *) (*$*) let y = 2 $ cinaps file.ml ---file.ml +++file.ml.corrected File "file.ml", line 5, characters 0-1: let x = 1 (*$ print_newline (); List.iter (fun s -> Printf.printf "let ( %s ) = Pervasives.( %s )\n" s s) ["+"; "-"; "*"; "/"] *) +|let ( + ) = Pervasives.( + ) +|let ( - ) = Pervasives.( - ) +|let ( * ) = Pervasives.( * ) +|let ( / ) = Pervasives.( / ) (*$*) let y = 2 $ echo $? 1 $ cp file.ml.corrected file.ml $ cinaps file.ml $ echo $? 0 #+end_src You can also pass =-i= to override the file in place in case of mismatch. For instance you can have a =cinaps= target in your build system to refresh the files in your project. ** Capturing text from the input In any form =(*$ ... *)= form, the variable =_last_text_block= contains the contents of the text between the previous =(*$ ... *)= form or beginning of file and the current form. For instance you can use it to write a block of code and copy it to a second block of code that is similar except for some simple substitution: #+begin_src ocaml (*$*) let rec power_int32 n p = if Int32.equal p 0 then Int32.one else Int32.mul n (power n (Int32.pred p)) (*$ print_string (Str.global_replace (Str.regexp "32") "64" _last_text_block) *) let rec power_int64 n p = if Int64.equal p 0 then Int64.one else Int64.mul n (power n (Int64.pred p)) (*$*) #+end_src Now, whenever you modify =power_int32=, you can just run cinaps to update the =power_int64= version. ** Sharing values across multiple files The toplevel directive ~#use~ works in CINAPS, and can be used to read in values from other files. For example, 1. In ~import.cinaps~, #+BEGIN_SRC ocaml (* -*- mode: tuareg -*- *) include StdLabels include Printf let all_fields = [ "name", "string"; "age", "int" ] #+END_SRC 2. In ~foo.ml~, #+BEGIN_SRC ocaml (*$ #use "import.cinaps";; List.iter all_fields ~f:(fun (name, type_) -> printf "\n\ external get_%s : unit -> %s = \"get_%s\"" name type_ name) *) external get_name : unit -> string = "get_name" external get_age : unit -> int = "get_age"(*$*) #+END_SRC 3. In ~stubs.h~, #+BEGIN_SRC C /*$ #use "import.cinaps";; List.iter all_fields ~f:(fun (name, _) -> printf "\n\ extern value get_%s(void);" name) */ extern value get_name(void); extern value get_age(void);/*$*/ #+END_SRC Etc. Note that the ~#use~ directive will read in OCaml from files of any extension. ~*.cinaps~ is a safe choice in the presence of jenga and dune, which by default try to use all ~*.ml~ files in the directory for the executables or library. ** Automatic reformatting of CINAPS output In files managed by automatic formatting tools such as ocp-indent or ocamlformat, the code need not come out of CINAPs already formatted correctly. ~cinaps.exe -styler FOO~ uses ~FOO~ to reformat its output, before diffing against the source file. cinaps-0.15.1/bin/000077500000000000000000000000001401152615700136255ustar00rootroot00000000000000cinaps-0.15.1/bin/dune000066400000000000000000000001421401152615700145000ustar00rootroot00000000000000(executables (names main) (public_names cinaps) (libraries cinaps) (preprocess no_preprocessing))cinaps-0.15.1/bin/main.ml000066400000000000000000000000301401152615700150740ustar00rootroot00000000000000let () = Cinaps.main () cinaps-0.15.1/bin/main.mli000066400000000000000000000000141401152615700152470ustar00rootroot00000000000000(* empty *) cinaps-0.15.1/cinaps.opam000066400000000000000000000014121401152615700152060ustar00rootroot00000000000000opam-version: "2.0" maintainer: "opensource@janestreet.com" authors: ["Jane Street Group, LLC "] homepage: "https://github.com/ocaml-ppx/cinaps" bug-reports: "https://github.com/ocaml-ppx/cinaps/issues" dev-repo: "git+https://github.com/ocaml-ppx/cinaps.git" license: "MIT" build: [ ["dune" "build" "-p" name "-j" jobs] ] depends: [ "ocaml" {>= "4.04"} "dune" {>= "2.0.0"} "re" {>= "1.8.0"} "ppx_jane" {with-test} "base-unix" ] synopsis: "Trivial metaprogramming tool" description: " Cinaps is a trivial Metaprogramming tool using the OCaml toplevel. It is based on the same idea as expectation tests. The user write some OCaml code inside special comments and cinaps make sure that what follows is what is printed by the OCaml code. " cinaps-0.15.1/dune-project000066400000000000000000000000401401152615700153710ustar00rootroot00000000000000(lang dune 1.10) (name cinaps) cinaps-0.15.1/src/000077500000000000000000000000001401152615700136445ustar00rootroot00000000000000cinaps-0.15.1/src/cinaps.ml000066400000000000000000000100051401152615700154470ustar00rootroot00000000000000open StdLabels let quote_string s = let is_substring s ~sub = let re = Re.(compile (seq [ rep any; str sub ])) in Re.execp re s in let rec find_tag n = let rec make_tag = function | 0 -> "" | n -> Printf.sprintf "%c%s" (Char.chr (Char.code 'a' + (n mod 26))) (make_tag (n / 26)) in let tag = make_tag n in if is_substring s ~sub:("|" ^ tag ^ "}") then find_tag (n + 1) else tag in let tag = find_tag 0 in Printf.sprintf "{%s|%s|%s}" tag s tag ;; type syntax = | Auto | This of Syntax.t let syntax_of_string = function | "auto" -> Auto | "c" -> This Syntax.c | "ocaml" -> This Syntax.ocaml | "sexp" -> This Syntax.sexp | s -> Printf.ksprintf invalid_arg "syntax_of_string (%S)" s ;; let syntax_of_filename fn = let unknown () = let pos = { Lexing.pos_fname = fn; pos_lnum = 1; pos_cnum = 0; pos_bol = 0 } in Parse.raisef ~pos "Don't know what syntax to use for this file, pass an explicit [-syntax] option" in match String.rindex fn '.' with | exception _ -> unknown () | i -> (match String.sub fn ~pos:(i + 1) ~len:(String.length fn - i - 1) with | "ml" | "mli" | "mll" | "mly" | "mld" -> Syntax.ocaml | "c" | "h" | "cpp" | "c++" | "cxx" -> Syntax.c | "sexp" -> Syntax.sexp | _ -> (match Filename.basename fn with | "jbuild" -> Syntax.sexp | _ -> unknown ())) ;; let process_file ~f ~syntax ~file_name ~file_contents ~copy_input = let lexbuf = Lexing.from_string file_contents in lexbuf.lex_curr_p <- { pos_fname = file_name; pos_cnum = 0; pos_lnum = 1; pos_bol = 0 }; Parse.run ~f ~syntax ~file_name ~file_contents ~copy_input ;; let main () = let syntax = ref Auto in let staged_output = ref None in let init_staged fn = let oc = open_out fn in staged_output := Some oc; Printf.fprintf oc "let () = Cinaps_runtime.init ()\n" in let args = Arg.align ([ ( "-syntax" , Arg.Symbol ([ "auto"; "c"; "ocaml" ], fun s -> syntax := syntax_of_string s) , " Syntax to use (default: auto)" ) ; ( "-staged" , String init_staged , "FILE Staged mode: write a .ml file that must be built and executed" ) ] @ Cinaps_runtime.args) in let usage = Printf.sprintf "%s " Sys.executable_name in let process_file fn = let syntax = match !syntax with | Auto -> syntax_of_filename fn | This s -> s in let file_contents = Cinaps_runtime.read_file fn in match !staged_output with | None -> let pos = { Lexing.pos_fname = fn; pos_lnum = 1; pos_cnum = 0; pos_bol = 0 } in Parse.raisef ~pos "%s" Non_staged_error.error_message | Some oc -> let append_code_block ~last_text_block:(pos, len) ~(code_start : Lexing.position) ~code = Printf.fprintf oc "let _last_text_block = Cinaps_runtime.input_sub %d %d;;\n# %d %S\n%*s%s\n;;\n" pos len code_start.pos_lnum code_start.pos_fname (code_start.pos_cnum - code_start.pos_bol) "" code in let copy_input pos len = Printf.fprintf oc "let () = Cinaps_runtime.copy_input %d %d;;\n" pos len in Printf.fprintf oc "let () = Cinaps_runtime.process_file\n\ \ ~file_name:%S\n\ \ ~file_contents:%s\n\ \ (fun () -> let module M = struct\n" fn (quote_string file_contents); process_file ~f:append_code_block ~syntax ~file_contents ~file_name:fn ~copy_input; Printf.fprintf oc "end in ());;\n" in try Arg.parse args process_file usage; (match !staged_output with | None -> () | Some oc -> Printf.fprintf oc "Cinaps_runtime.exit ();;\n"; close_out oc); Cinaps_runtime.exit () with | Parse.Error { pos; msg } -> Printf.eprintf "File %S, line %d, character %d:\nError: %s\n" pos.pos_fname pos.pos_lnum (pos.pos_cnum - pos.pos_bol) msg; exit 1 ;; cinaps-0.15.1/src/dune000066400000000000000000000001311401152615700145150ustar00rootroot00000000000000(library (name cinaps) (libraries unix re cinaps.runtime) (preprocess no_preprocessing))cinaps-0.15.1/src/non_staged_error.ml000066400000000000000000000002161401152615700175270ustar00rootroot00000000000000let error_message = "the direct mode of cinaps is no longer supported. Please use the \"cinaps\" stanza in \ your dune file instead." ;; cinaps-0.15.1/src/non_staged_error.mli000066400000000000000000000001231401152615700176750ustar00rootroot00000000000000(** Error message printed when not passing [-staged] *) val error_message : string cinaps-0.15.1/src/parse.ml000066400000000000000000000067311401152615700153170ustar00rootroot00000000000000open StdLabels open Syntax exception Error of { pos : Lexing.position ; msg : string } let raisef ~pos fmt = Printf.ksprintf (fun msg -> raise (Error { pos; msg })) fmt let rec advance_bol s (bol : Lexing.position) ~start ~stop = if start >= stop then bol else ( match s.[start] with | '\n' -> advance_bol s { bol with pos_lnum = bol.pos_lnum + 1; pos_bol = start + 1 } ~start:(start + 1) ~stop | _ -> advance_bol s bol ~start:(start + 1) ~stop) ;; let rec loop ~copy_input ~syntax ~f ~file_contents ~keep ~text_start ~bol ~pos = match Re.exec_opt syntax.comment_start_dollar file_contents ~pos with | None -> if keep then copy_input text_start (String.length file_contents - text_start) | Some groups -> let start = Re.Group.start groups 0 in let stop = Re.Group.stop groups 0 in (match Re.exec_opt syntax.comment_end_anchored file_contents ~pos:stop with | Some groups -> let stop = Re.Group.stop groups 0 in let start = if keep then text_start else start in copy_input start (stop - start); let bol = advance_bol file_contents bol ~start:pos ~stop in loop ~copy_input ~syntax ~f ~file_contents ~keep:true ~pos:stop ~bol ~text_start:stop | None -> let bol = advance_bol file_contents bol ~start:pos ~stop in let last_text_block = text_start, start - text_start in let start = if keep then text_start else start in let code_start = { bol with Lexing.pos_cnum = stop } in let code_stop, keep_next, pos = code ~copy_input ~syntax ~file_contents ~depth:0 ~pos:stop ~code_start in let code = let code_start = code_start.pos_cnum in String.sub file_contents ~pos:code_start ~len:(code_stop - code_start) in copy_input start (pos - start); f ~last_text_block ~code_start ~code; let bol = advance_bol file_contents bol ~start:stop ~stop:pos in loop ~copy_input ~syntax ~f ~file_contents ~keep:keep_next ~text_start:pos ~bol ~pos) and code ~copy_input ~syntax ~file_contents ~depth ~pos ~code_start = match Re.exec_opt syntax.comment_end_or_dollar_comment_end_or_comment_start_if_rec_comment file_contents ~pos with | None -> raisef ~pos:code_start "End of file reached before end of code block" | Some groups -> let start = Re.Group.start groups 0 in let stop = Re.Group.stop groups 0 in if Re.Group.test groups 3 then (* Group 3 matched --> this is comment_start *) code ~copy_input ~syntax ~file_contents ~code_start ~depth:(depth + 1) ~pos:stop else if Re.Group.test groups 2 then if (* Group 2 matched --> this is dollar_comment_end *) depth = 0 then start, true, stop else code ~copy_input ~syntax ~file_contents ~depth:(depth - 1) ~pos:stop ~code_start else ( assert (Re.Group.test groups 1); (* Group 1 matched --> this is comment_end *) if depth = 0 then start, false, stop else code ~copy_input ~syntax ~file_contents ~depth:(depth - 1) ~pos:stop ~code_start) ;; let run ~syntax ~f ~file_name ~file_contents ~copy_input = loop ~copy_input ~syntax ~f ~file_contents ~keep:true ~text_start:0 ~bol:{ pos_fname = file_name; pos_lnum = 1; pos_bol = 0; pos_cnum = 0 } ~pos:0 ;; cinaps-0.15.1/src/parse.mli000066400000000000000000000005501401152615700154610ustar00rootroot00000000000000val run : syntax:Syntax.t -> f:(last_text_block:int * int -> code_start:Lexing.position -> code:string -> unit) -> file_name:string -> file_contents:string -> copy_input:(int -> int -> unit) -> unit exception Error of { pos : Lexing.position ; msg : string } val raisef : pos:Lexing.position -> ('a, unit, string, _) format4 -> 'a cinaps-0.15.1/src/runtime/000077500000000000000000000000001401152615700153275ustar00rootroot00000000000000cinaps-0.15.1/src/runtime/cinaps_runtime.ml000066400000000000000000000106701401152615700207050ustar00rootroot00000000000000let split_string_on_char ~sep s = String.split_on_char sep s open StdLabels let in_place = ref false let styler = ref None let diff_command = ref None let use_color = ref false let args = let open Arg in [ "-i", Set in_place, " Update the file in-place" ;"-diff-cmd", String (fun s -> diff_command := Some s), " Diff command when using code expectations" ; "-no-color", Clear use_color, " Don't use colors when printing errors" ; "-styler", String (fun s -> styler := Some s), " Code styler" ] let init () = let usage = Printf.sprintf "%s " Sys.executable_name in let anon fn = raise (Arg.Bad (Printf.sprintf "Don't know what to do with %S." fn)) in Arg.parse (Arg.align args) anon usage module Print_diff = struct let patdiff_cmd () = let args = List.concat [ ["-keep-whitespace"]; ["-location-style omake"]; (if !use_color then ["-unrefined"] else ["-ascii"]); ] in String.concat ~sep:" " ("patdiff" :: args) let print ~file1 ~file2 = let exec cmd = let cmd = Printf.sprintf "%s %s %s 1>&2" cmd (Filename.quote file1) (Filename.quote file2) in match Sys.command cmd with | 0 -> true | 1 -> false | n -> Printf.eprintf "%S exited with code %d\n" cmd n; exit 2 in match !diff_command with | Some s -> ignore (exec s : bool) | None -> if exec (patdiff_cmd ()) then ( Printf.eprintf "File \"%s\", line 1, characters 0-0:\n%!" file1; ignore (exec "diff -u" : bool); ) end let failure = ref false let current_file_contents = ref "" let copy_input pos len = output_substring stdout !current_file_contents pos len let input_sub pos len = String.sub !current_file_contents ~pos ~len let protect ~finally ~f = match f () with | x -> finally (); x | exception e -> finally (); raise e let read_file fn = let ic = open_in_bin fn in let len = in_channel_length ic in let s = really_input_string ic len in close_in ic; s let write_file fn s = let oc = open_out_bin fn in output_string oc s; close_out oc let process_file ~file_name ~file_contents f = let tmp_fn, oc = Filename.open_temp_file "cinaps" (Filename.extension file_name) in let expected = protect ~finally:(fun () -> Sys.remove tmp_fn) ~f:(fun () -> let stdout_copy = Unix.dup Unix.stdout in Unix.dup2 (Unix.descr_of_out_channel oc) Unix.stdout; close_out oc; current_file_contents := file_contents; f (); flush stdout; Unix.close Unix.stdout; Unix.dup2 stdout_copy Unix.stdout; Unix.close stdout_copy; match !styler with | Some cmd -> begin let cmd = String.concat ~sep:"" (match split_string_on_char cmd ~sep:'%' with | [] -> assert false | x :: l -> x :: List.map l ~f:(fun s -> let len = String.length s in if len > 0 && s.[0] = 'i' then (Filename.quote file_name) ^ String.sub s ~pos:1 ~len:(len - 1) else "%" ^ s)) in let cmd = Printf.sprintf "%s %s" cmd (Filename.quote tmp_fn) in let ic = Unix.open_process_in cmd in let s = let file_len = String.length file_contents in let buf = Buffer.create file_len in try Buffer.add_channel buf ic file_len; while true do Buffer.add_channel buf ic 65536 done; assert false with End_of_file -> Buffer.contents buf in match Unix.close_process_in ic with | WEXITED 0 -> s | WEXITED n -> Printf.eprintf "command exited with code %d: %s\n" n cmd; exit 1 | WSIGNALED n -> Printf.eprintf "command got signal %d: %s\n" n cmd; exit 1 | WSTOPPED _ -> assert false end | _ -> read_file tmp_fn) in let corrected_fn = file_name ^ ".cinaps-corrected" in if file_contents = expected then begin if Sys.file_exists corrected_fn then Sys.remove corrected_fn end else if !in_place then write_file file_name expected else begin write_file corrected_fn expected; match !diff_command with | Some "-" -> (* keep the corrected file but do not output the diff *) () | _ -> failure := true; Print_diff.print ~file1:file_name ~file2:corrected_fn end let exit () = exit (if !failure then 1 else 0) cinaps-0.15.1/src/runtime/cinaps_runtime.mli000066400000000000000000000005051401152615700210520ustar00rootroot00000000000000 val args : (string * Arg.spec * string) list (* For statged mode only *) val init : unit -> unit val exit : unit -> _ val process_file : file_name:string -> file_contents:string -> (unit -> unit) -> unit val copy_input : int -> int -> unit val input_sub : int -> int -> string val read_file : string -> string cinaps-0.15.1/src/runtime/dune000066400000000000000000000001541401152615700162050ustar00rootroot00000000000000(library (name cinaps_runtime) (public_name cinaps.runtime) (libraries unix) (preprocess no_preprocessing))cinaps-0.15.1/src/syntax.ml000066400000000000000000000016021401152615700155230ustar00rootroot00000000000000type t = { comment_start_dollar : Re.re ; comment_end_or_dollar_comment_end_or_comment_start_if_rec_comment : Re.re ; comment_end_anchored : Re.re } let make ~comment_start ~comment_end ~is_ocaml = { comment_start_dollar = Re.compile (Re.seq [ comment_start; Re.char '$' ]) ; comment_end_or_dollar_comment_end_or_comment_start_if_rec_comment = Re.compile (Re.alt (Re.group comment_end :: Re.group (Re.seq [ Re.char '$'; comment_end ]) :: (if is_ocaml then [ Re.group comment_start ] else []))) ; comment_end_anchored = Re.compile (Re.seq [ Re.start; comment_end ]) } ;; let ocaml = make ~comment_start:(Re.str "(*") ~comment_end:(Re.str "*)") ~is_ocaml:true let c = make ~comment_start:(Re.str "/*") ~comment_end:(Re.str "*/") ~is_ocaml:false let sexp = make ~comment_start:(Re.str "#|") ~comment_end:(Re.str "|#") ~is_ocaml:false cinaps-0.15.1/src/syntax.mli000066400000000000000000000003031401152615700156710ustar00rootroot00000000000000type t = { comment_start_dollar : Re.re ; comment_end_or_dollar_comment_end_or_comment_start_if_rec_comment : Re.re ; comment_end_anchored : Re.re } val ocaml : t val c : t val sexp : t cinaps-0.15.1/test/000077500000000000000000000000001401152615700140345ustar00rootroot00000000000000cinaps-0.15.1/test/dune000066400000000000000000000005631401152615700147160ustar00rootroot00000000000000(rule (deps test_staged.ml) (targets test_staged_gen.ml) (action (bash "%{bin:cinaps} -staged test_staged_gen.ml test_staged.ml"))) (executables (names test_staged_gen) (modules test_staged_gen) (libraries cinaps.runtime) (preprocess (pps ppx_jane -allow-toplevel-expression))) (alias (name runtest) (deps test_staged_gen.exe) (action (bash ./test_staged_gen.exe)))cinaps-0.15.1/test/test_staged.ml000066400000000000000000000007121401152615700166740ustar00rootroot00000000000000(*$ open StdLabels open Printf let () = printf "\ntoto\n" *) toto (*$*) (*$ printf "\n";; List.iter ["unit"; "string"] ~f:(fun s -> printf "let foo_%s = foo_%s\n" s s) *) let foo_unit = foo_unit let foo_string = foo_string (*$*) (*$ let blah () = printf "42" let foo () = printf "1" let bar () = printf "2" $*) let f = function | (*$blah()*)42(*$*) -> "blah" | (*$foo() *)1(*$*) -> "foo" | (*$bar() *)2(*$*) -> "bar"