Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

895 lines (767 sloc) 36.127 kB
(******************************************************************************)
(* TODO *)
(******************************************************************************)
(*
macro Or a la merd (try or_left with -> or_right)
Pcaml.str_item:
[ [ "type"; LIDENT "nogen"; tdl = LIST1 type_declaration SEP "and" ->
<:str_item< type $list:tdl$ >>
| "type"; tdl = LIST1 type_declaration SEP "and" ->
let sil = gen_ioxml_impl loc tdl in
Pcaml.sig_item:
[ [ "type"; LIDENT "nogen"; tdl = LIST1 type_declaration SEP "and" ->
<:sig_item< type $list:tdl$ >>
| "type"; tdl = LIST1 type_declaration SEP "and" ->
need put too in sig_item ?
look in common.* to do more macro (and also in my docs/langage)
put the tricks i have in perl
aspect ==> need fix_caml ? or can do with camlp4 (i think yes, but complicated)
profiling mem/cpu/overhead/....
pr pr2 ....
emacs tricks (C-M-1, ...)
au moins pour le debug
generalise my stuff so that it is easy to add functionnality
(kind of tools a la haskell je_sais_plus_lenom)
faire meilleur lang
where
comprehension
[.. syntax (just from ...) do the desugar as in haskell)
`...` perhaps with help of lexer (can extend the lexer easily ?)
type class ?
layout ?
section
joly syntax pour les types ([], ())
autogenerated accessor function
\x -> ... NON visuellement dur a voir
my stuff with self fun ?
suppr let rec
class Show par exemple, peut etre fait
en passant en param a la function genere automatiquement 2 3 foncs
(genre string_of_var, connection_between, ...) ?
can we make class stuff with my fix_caml ?
just need pass around the dictionnary
pb let obj' = f obj
mieux obj = f obj
encore mieux macro, that "modify" obj
comme let obj ||= f
(ex ++ s'ecrirait let i ||= (+1)
*)
(******************************************************************************)
(*
design interactivly: (=~ design and call macroexpand of lisp)
$~> ocaml
#load "camlp4o.cma";;
#load "pa_extend.cmo";;
add Extend rule, copy paste in interpreter
Grammar.Entry.parse expr (Stream.of_string "2 + 3");;
expr is already binded with the expr for caml
can use the exception tricks to display (as in exception Print of type_decl)
using p4 in p4 (with pattern that are quotation) is confusing
=> better to do a violent match over the real Ast type
good example in pa_o.ml (defintion of caml grammar in p4)
*)
(******************************************************************************)
(*
compile it:
ocamlc -c -pp 'camlp4o pa_extend.cmo q_MLast.cmo -impl' -I +camlp4 -impl macro.ml4
test output:
camlp4o ./macro.cmo pr_o.cmo common.ml
use in file (handled by OcamlMakefile):
put at start of your file (*pp camlp4o ./macro.cmo *)
or manually compile with ocamlc -c -pp "camlp4o ./macro.cmo" -g my_file.ml
*)
(******************************************************************************)
open Pcaml
open MLast
(* same as in common *)
let (+>) o f = f o
let rec zip xs ys =
match (xs,ys) with
| ([],_) -> []
| (_,[]) -> []
| (x::xs,y::ys) -> (x,y)::zip xs ys
let foldl1 p = function x::xs -> List.fold_left p x xs | _ -> failwith "foldl1"
let rec join_gen a = function
| [] -> []
| [x] -> [x]
| x::xs -> x::a::(join_gen a xs)
let _counter = ref 0
let counter () = (_counter := !_counter +1; !_counter)
(* just cos dont want care about location and pass it around to each func *)
(* old: let l = (1,1) *)
let l = (Lexing.dummy_pos, Lexing.dummy_pos)
(******************************************************************************)
(* inspired by an example in the camlp4 tutorial
NEED recent version of camlp4 > 3.06+6 (available in the cvs only)
update=tywith do better ? ioXml do better ?
update: I made this a long time ago, maybe in 2001, long before
tywith, or typeconf, or sexplib, json-static. It was working but limited
to not too complex type, it has no object or module support I think. So
tywith/typeconf were definitely better (and generic).
It auto-genarate string_of_<name_type> and print_<name_type> function.
After defining a type, you can normally use the corresponding string_of function.
For polymorphic type, you need to pass as a parameter the string_of function
of the corresponding polymorphic variable
ex:
from "type t = int * int"
it generates
let rec string_of_t a0 =
match a0 with
a24, a25 -> ((("(" ^ string_of_int a24) ^ ",") ^ string_of_int a25) ^ ")"
and print_t a = print_string (string_of_t a)
from "type ('a, 'b) either = Left of 'a | Right of 'b"
it generates
let rec string_of_either (str__of_a, str__of_b) a0 =
match a0 with
Left a24 -> (("Left" ^ "(") ^ str__of_a a24) ^ ")"
| Right a26 -> (("Right" ^ "(") ^ str__of_b a26) ^ ")"
and print_either funs a = print_string (string_of_either funs a)
as i have not access to the source file of caml, you certainly have to put
in one of your source file those definitions:
let string_of_list f xs =
"[" ^ (xs +> List.map f +> String.concat ";" ) ^ "]"
let string_of_array f xs =
"[|" ^ (xs +> Array.to_list +> List.map f +> String.concat ";") ^ "|]"
let string_of_option f = function
| None -> "None "
| Some x -> "Some " ^ (f x)
let print_bool x = print_string (if x then "True" else "False")
let print_list pr xs =
do { print_string "["; List.iter (fun x -> pr x; print_string ",") xs; print_string "]" }
let print_option pr = function
| None -> print_string "None"
| Some x -> print_string "Some ("; pr x; print_string ")"
*)
(* COMMENT START
let _ =
DELETE_RULE
Pcaml.str_item: "type"; LIST1 Pcaml.type_declaration SEP "and"
END;
EXTEND
Pcaml.str_item:
[ [ "type"; tdl = LIST1 Pcaml.type_declaration SEP "and" ->
let name () = "a" ^ string_of_int (counter ()) in
(* subtil bug, when we have only one param, we cant construct a tuple with one param,
we should think that (1) and 1 are treated the same way, but seems this work
is done in caml in the parser, which mean that we must not give to caml an Ast with
a 1-uple
*)
let ex_tuple = function
| [] -> failwith "pb"
| [x] -> x
| xs -> ExTup (l,xs)
in
let pa_tuple = function
| [] -> failwith "pb"
| [x] -> x
| xs -> PaTup (l,xs)
in
let funcs = tdl +> List.map (fun ((l,str), param_polymorphs, ctyp, z) ->
let join_app xs = xs +> foldl1 (fun a e -> <:expr< $a$ ^ $e$>>) in
let join_virg xs = xs +> join_gen (ExStr (l, ",")) in
let name_module_func = function
| TyLid (l, s) -> ExLid(l, "string_of_" ^ s)
| TyAcc (_, TyUid (_,file), TyLid (_,s)) ->
(* Module.string_of ....
ExAcc(l, ExUid (l,file), ExLid(l, "string_of_" ^ s))
but dont work that much cos builtin lib or modules have not those function
*)
ExLid(l, String.lowercase file ^ "_" ^ "string_of_" ^ s)
| _ -> failwith "pb"
in
(* TODOSTYLE? function fmatch id patt expr who put the None, ... *)
let rec body_ctyp id = function
| (TyLid (_) | TyAcc (_)) as c -> ExApp (l,name_module_func c, ExLid (l,id))
(* | TyUid of loc and string *)
| TyQuo (l, s) -> ExApp (l, ExLid(l, "str__of_" ^ s), ExLid (l,id))
| TySum (l,_bool, xs) ->
ExMat(l, ExLid (l, id),
xs +> List.map (fun (l, s, ctyps) ->
let newids = xs +> List.map (fun _ -> name ()) in
match ctyps, newids with
| ([],_) -> (PaUid(l, s), None, ExStr (l,s))
| (x::xs,id::ids) ->
let patt = zip xs ids +>
List.fold_left
(fun a (e,id) -> PaApp (l, a, PaLid (l,id)))
(PaApp (l, PaUid(l, s), PaLid(l, id))) in
(patt, None,
zip (x::xs) (id::ids) +> List.map (fun (e,id) -> body_ctyp id e) +> join_virg +>
(fun xs -> [ExStr (l,s); ExStr (l,"(")] @ xs @ [ExStr (l,")")]) +> join_app
)
| _ -> failwith "pb"
)
)
| TyTup (l, xs) ->
let newids = xs +> List.map (fun _ -> name ()) in
ExMat(l, ExLid (l,id),
[PaTup(l, newids +> List.map (fun id -> PaLid (l,id))),
None,
zip xs newids +> List.map (fun (e,id) -> body_ctyp id e) +> join_virg +>
(fun xs -> [ExStr (l,"(")] @ xs @ [ExStr (l,")")]) +> join_app
]
)
| TyArr (l,c1,c2) -> ExStr(l, "<fun>")
| TyApp (l,c1,c2) ->
let rec extract_all_params acc = function
| TyApp (l,c1', c2') -> extract_all_params (acc @ [c2']) c1'
| x -> (x, acc) in
let (type_parameted, params) = extract_all_params [] (TyApp (l, c1, c2)) in
let funcs = params +> List.map (fun c ->
let id = name () in
let f = body_ctyp id c in
ExFun (l, [PaLid(l, id), None, f]))
in
(match type_parameted with
| (TyLid (_) | TyAcc (_)) as c ->
ExApp (l, ExApp (l, name_module_func c, ex_tuple funcs), ExLid (l,id))
| _ -> ExStr (l,"<illegal syntax in type, should be a typeconst>")
)
| TyRec (l, _bool, xs) ->
let newids = xs +> List.map (fun _ -> name ()) in
ExMat(l, ExLid (l, id),
[ PaRec (l, zip xs newids +> List.map (fun ((_,e,_,_), id) -> PaLid(l, e), PaLid(l, id))),
None,
zip xs newids
+> List.map
(fun ((l,s,_b,e),id) -> [ExStr(l,s); ExStr(l," = ");body_ctyp id e] +> join_app)
+> join_virg
+> (fun xs -> [ExStr (l,"{")] @ xs @ [ExStr (l,"}")]) +> join_app
])
(* TODO when needed
| TyAli of loc and ctyp and ctyp
| TyAny of loc
| TyCls of loc and list string
| TyLab of loc and string and ctyp
| TyMan of loc and ctyp and ctyp
| TyOlb of loc and string and ctyp
| TyPol of loc and list string and ctyp
| TyObj of loc and list (string * ctyp) and bool
| TyVrn of loc and list row_field and option (option (list string))
and row_field =
| RfTag of string and bool and list ctyp
| RfInh of ctyp
*)
| _ -> (ExStr (l, "<not yet implemnted>"))
in
let f_str_func_params body =
(* currifie:
param_polymorphs +> List.rev +> List.fold_left (fun acc (str_poly, (_,_)) ->
ExFun(l, [(PaLid (l, name_f_str_params str_poly),None, acc)]))
body
*)
if param_polymorphs = [] then body
else ExFun (l, [pa_tuple
(param_polymorphs +> List.map (fun (str_poly,(_,_)) ->
PaLid (l, "str__of_" ^ str_poly))),
None, body])
in
[(PaLid (l, "string_of_" ^ str), (* let string_of... *)
f_str_func_params (* str__a str__b ... *)
(ExFun(l, [(PaLid (l,"a0"), None, (* a0 = .... *)
(body_ctyp "a0" ctyp))]))) (* match a with .... *)
;(PaLid (l, "print_" ^ str),
(if param_polymorphs = []
then fun e -> e
else fun e -> (ExFun (l, [PaLid (l, "funs"), None, e]))
)
(ExFun (l, [(PaLid (l,"a")), None,
ExApp (l, ExLid (l, "print_string"),
if param_polymorphs = []
then ExApp(l, ExLid (l, "string_of_" ^ str), ExLid (l, "a"))
else ExApp (l,
ExApp (l, ExLid (l, "string_of_" ^ str),
ExLid (l, "funs")),
ExLid (l, "a")))])))
])
in
let recursif = true in
(StDcl (loc, [(StTyp (loc, tdl));StVal (loc, recursif, funcs +> List.flatten)]))
]]
;
END
;;
END COMMENT *)
(*
let x = Grammar.Entry.parse str_item (Stream.of_string "type synon = int * int")
let x = Grammar.Entry.parse str_item (Stream.of_string "type 'a numdict = C of ('a -> 'a)")
let x = Grammar.Entry.parse str_item (Stream.of_string "type test = C1 of string * string | C2 and t2 = C3 | C4")
let x = Grammar.Entry.parse str_item (Stream.of_string "type ('a,'b) test = C1 of 'a | C2 of 'b")
let x = Grammar.Entry.parse str_item (Stream.of_string "type point = {x: int; y:int}")
let x = Grammar.Entry.parse str_item (Stream.of_string "type ('a,'b) assoc = ('a * 'b) list")
let x = Grammar.Entry.parse str_item (Stream.of_string "type ('a,'b) vec = ('a , 'b) assoc")
let x = Grammar.Entry.parse str_item (Stream.of_string "type robot_list = robot IntMap.t")
let x = Grammar.Entry.parse expr (Stream.of_string "match a with {x = a; y = b} -> a + b")
let x = Grammar.Entry.parse expr (Stream.of_string "match a with (a,b,c,d) -> a + b + c + d")
let x = Grammar.Entry.parse expr (Stream.of_string "match a with C1 (s, s2) -> s | C2 s -> s | C3 -> s")
let x = Grammar.Entry.parse str_item (Stream.of_string "let rec fact x = if x = 0 then 1 else x * fact (x -1);; ")
let x = Grammar.Entry.parse str_item (Stream.of_string "let print_toto f a = function () -> ();; ")
let x = Grammar.Entry.parse str_item (Stream.of_string "let print_toto f1 f2 a = function () -> ();; ")
let x = Grammar.Entry.parse str_item (Stream.of_string "let print_toto (f1,f2) a = function () -> ();; ")
let x = Grammar.Entry.parse str_item (Stream.of_string "let print_assoc (f1,f2) a0 = print_list (fun a -> function () -> ());; ")
let x = Grammar.Entry.parse str_item (Stream.of_string "let print_assoc (f1,f2) a0 = IntMap.print_list (fun a -> function () -> ());; ")
let x = Grammar.Entry.parse expr (Stream.of_string "1 + 1")
let x = Grammar.Entry.parse expr (Stream.of_string "\"tptp\" ^ string_of a")
let x = Grammar.Entry.parse expr (Stream.of_string "print_string (string_of a)")
let t = macro_expand "type t = int * int;;"
let t = macro_expand "type test = C1 of string * string | C2 and t2 = C3 | C4"
let t = macro_expand "type 'a test = C1 of string * string | C2 | C3 of 'a and t2 = C3 | C4"
let t = macro_expand "type ('a,'b) either = Left of 'a | Right of 'b"
let t = macro_expand "type color_test = Red | Yellow"
let t = macro_expand "type ('a,'b) assoc = ('a * 'b) list"
let t = macro_expand "type 'a numdict = C of ('a -> 'a)"
let t = macro_expand "type 'a numdict = NumDict of (('a-> 'a -> 'a) * ('a-> 'a -> 'a) * ('a-> 'a -> 'a) * ('a -> 'a))"
let t = macro_expand "type 'a bintree = Leaf of 'a | Branch of ('a bintree * 'a bintree)"
let t = macro_expand "type ('a,'b) assoc = ('a * 'b) list"
let t = macro_expand "type ('a,'b) vec = ('a , 'b) assoc"
let t = macro_expand "type vector = (float * float * float)"
let t = macro_expand "type point = {x: int; y:int}"
let t = macro_expand "type robot_list = robot IntMap.t"
let t = macro_expand "type robot_list = IntMap.t"
*)
(******************************************************************************)
(*
map
fold
fold_some
apres pourra faire facilement des trucs du genre get_all_vars,
...
facto code ?
'a 'b --> 'c 'd pour map
intmap fold = ?
les fold des libs de caml = ?
*)
(******************************************************************************)
(*
EXTEND
expr: BEFORE "simple"
[[ "do"; "{"; e1 = expr; "}" ->
<:expr< do { $e1$ } >> ]];
END;;
*)
(* can also do <:expr< let _ = $e1$ in () >> ]]; *)
EXTEND
expr: BEFORE "simple"
[[ "do"; "{"; e1 = expr; "}" ->
ExSeq ((Lexing.dummy_pos,Lexing.dummy_pos),[e1])
]];
END;;
(******************************************************************************)
(* use:
let g = (x + y)
where x = 1
and y = 1
*)
EXTEND
expr:
[[ e2 = expr; "where"; rest = LIST1 Pcaml.let_binding SEP "and" ->
rest +> List.rev +> List.fold_left (fun acc (patt, expr) ->
ExLet(l, false, [patt,expr], acc)) e2
]];
END;;
(*
let x = Grammar.Entry.parse expr (Stream.of_string "let x = 1 in let y a = 1 in x + y");;
let t = macro_expand "let2 x = 1 in 1"
let t = macro_expand "x where x = 1"
let t = macro_expand "x + y where x = 1 and y = 1"
*)
(******************************************************************************)
(*
use:
{ x + y | (x,y) <- [(1,1);(2,2);(3,3)] and x > 2 and y < 3}
TODO support only one generator for the moment
*)
(*
EXTEND
expr:
[[
"{{"; e1 = expr; "|"; p1 = patt; "<-"; e2 = expr; "}}" ->
let maps = (ExAcc (l, ExUid (l, "List"), ExLid (l,"map"))) in
ExApp (l, ExApp(l, maps,
ExFun (l, [p1, None, e1])
), e2)
| "{{"; e1 = expr; "|"; p1 = patt; "<-"; e2 = expr; "and"; e3s = LIST1 expr SEP "and"; "}}" ->
let maps = (ExAcc (l, ExUid (l, "List"), ExLid (l,"map"))) in
let filters =(ExAcc (l, ExUid (l, "List"), ExLid (l,"filter"))) in
ExApp (l,
ExApp(l, maps,ExFun (l, [p1, None, e1])),
e3s +> List.fold_left (fun acc expr ->
ExApp (l,
ExApp(l, filters, ExFun(l, [p1, None, expr])),
acc)
)
e2)
]];
END;;
*)
(*
[ expr1 | x <- expr2] ----> expr2 +> List.map (fun x -> expr1)
[ expr1 | x <- expr2, x > 2] ----> expr2 +> List.filter (fun x -> x > 2) +> List.map (fun x -> expr1)
TODO better than | to separate filter
*)
(******************************************************************************)
(*
use:
let x = {1 .. 10} +> List.map (fun i -> i)
you need space between token (dont know really why)
you need the enum function: let rec enum x n = if x = n then [n] else x::enum (x+1) n
*)
(*
EXTEND
expr:
[[
"{{"; e1 = expr; ".."; e2 = expr; "}}" ->
<:expr<enum $e1$ $e2$>>
]];
END;;
*)
(******************************************************************************)
(*
EXTEND
expr: BEFORE "simple"
[[
e1 = expr; "to"; e2 = expr; "to"; e3 = expr ->
<:expr<e2 $e1$ $e3$>>
]];
END;;
*)
(******************************************************************************)
(*
let add_update_plan w e = w.update_plan <- e::w.update_plan
sucks cos no first class field
perhaps need a preprocessor over record to let the field be first class
indeed :) camlp4
*)
EXTEND
expr:BEFORE "simple"
[ [
"modify"; record = NEXT; "."; field = LIDENT ; f = NEXT ->
<:expr< $record$.$lid:field$ := $f$ $record$.$lid:field$>>
]];
END;;
(*
# type point = {mutable x:int; mutable y:int};;
# let o = { x= 0; y = 0};;
# modify o.y succ;;
I haven't tested this extension any further, but the main issue I can see is
that "modify" becomes a keyword, which can be a problem if there are some
variables with that name in your code.
-- Virgile Prevosto <virgile.prevosto@lip6.fr>
*)
(******************************************************************************)
(*
Original version, without quotation
let _ =
DELETE_RULE
Pcaml.str_item: "type"; LIST1 Pcaml.type_declaration SEP "and"
END;
EXTEND
Pcaml.str_item:
[ [ "type"; tdl = LIST1 Pcaml.type_declaration SEP "and" ->
let name () = "a" ^ string_of_int (counter ()) in
(* subtil bug, when we have only one param, we cant construct a tuple with one param,
we should think that (1) and 1 are treated the same way, but seems this work
is done in caml in the parser, which mean that we must not give to caml an Ast with
a 1-uple
*)
let ex_tuple = function
| [] -> failwith "pb"
| [x] -> x
| xs -> ExTup (l,xs)
in
let pa_tuple = function
| [] -> failwith "pb"
| [x] -> x
| xs -> PaTup (l,xs)
in
let funcs = tdl +> List.map (fun ((l,str), param_polymorphs, ctyp, z) ->
let join_app xs = xs +> foldl1 (fun a e -> ExApp(l, ExApp (l, ExLid (l, "^"), a), e)) in
let join_virg xs = xs +> join_gen (ExStr (l, ",")) in
let name_module_func = function
| TyLid (l, s) -> ExLid(l, "string_of_" ^ s)
| TyAcc (_, TyUid (_,file), TyLid (_,s)) -> ExAcc(l, ExUid (l,file), ExLid(l, "string_of_" ^ s))
| _ -> failwith "pb"
in
(* TODOSTYLE? function fmatch id patt expr who put the None, ... *)
let rec body_ctyp id = function
| (TyLid (_) | TyAcc (_)) as c -> ExApp (l,name_module_func c, ExLid (l,id))
(* | TyUid of loc and string *)
| TyQuo (l, s) -> ExApp (l, ExLid(l, "str__of_" ^ s), ExLid (l,id))
| TySum (l, xs) ->
ExMat(l, ExLid (l, id),
xs +> List.map (fun (l, s, ctyps) ->
let newids = xs +> List.map (fun _ -> name ()) in
match ctyps, newids with
| ([],_) -> (PaUid(l, s), None, ExStr (l,s))
| (x::xs,id::ids) ->
let patt = zip xs ids +> List.fold_left
(fun a (e,id) -> PaApp (l, a, PaLid (l,id))
) (PaApp (l, PaUid(l, s), PaLid(l, id))) in
(patt, None,
zip (x::xs) (id::ids) +> List.map (fun (e,id) -> body_ctyp id e) +> join_virg +>
(fun xs -> [ExStr (l,s); ExStr (l,"(")] @ xs @ [ExStr (l,")")]) +> join_app
)
| _ -> failwith "pb"
)
)
| TyTup (l, xs) ->
let newids = xs +> List.map (fun _ -> name ()) in
ExMat(l, ExLid (l,id),
[PaTup(l, newids +> List.map (fun id -> PaLid (l,id))),
None,
zip xs newids +> List.map (fun (e,id) -> body_ctyp id e) +> join_virg +>
(fun xs -> [ExStr (l,"(")] @ xs @ [ExStr (l,")")]) +> join_app
]
)
| TyArr (l,c1,c2) -> ExStr(l, "<fun>")
| TyApp (l,c1,c2) ->
let rec extract_all_params acc = function
| TyApp (l,c1', c2') -> extract_all_params (acc @ [c2']) c1'
| x -> (x, acc) in
let (type_parameted, params) = extract_all_params [] (TyApp (l, c1, c2)) in
let funcs = params +> List.map (fun c ->
let id = name () in
let f = body_ctyp id c in
ExFun (l, [PaLid(l, id), None, f]))
in
(match type_parameted with
| (TyLid (_) | TyAcc (_)) as c ->
ExApp (l, ExApp (l, name_module_func c, ex_tuple funcs), ExLid (l,id))
| _ -> ExStr (l,"<illegal syntax in type, should be a typeconst>")
)
| TyRec (l, xs) ->
let newids = xs +> List.map (fun _ -> name ()) in
ExMat(l, ExLid (l, id),
[ PaRec (l, zip xs newids +> List.map (fun ((_,e,_,_), id) -> PaLid(l, e), PaLid(l, id))),
None,
zip xs newids
+> List.map
(fun ((l,s,_b,e),id) -> [ExStr(l,s); ExStr(l," = ");body_ctyp id e] +> join_app)
+> join_virg
+> (fun xs -> [ExStr (l,"{")] @ xs @ [ExStr (l,"}")]) +> join_app
])
(* TODO when needed
| TyAli of loc and ctyp and ctyp
| TyAny of loc
| TyCls of loc and list string
| TyLab of loc and string and ctyp
| TyMan of loc and ctyp and ctyp
| TyOlb of loc and string and ctyp
| TyPol of loc and list string and ctyp
| TyObj of loc and list (string * ctyp) and bool
| TyVrn of loc and list row_field and option (option (list string))
and row_field =
| RfTag of string and bool and list ctyp
| RfInh of ctyp
*)
| _ -> (ExStr (l, "<not yet implemnted>"))
in
let f_str_func_params body =
(* currifie:
param_polymorphs +> List.rev +> List.fold_left (fun acc (str_poly, (_,_)) ->
ExFun(l, [(PaLid (l, name_f_str_params str_poly),None, acc)]))
body
*)
if param_polymorphs = [] then body
else ExFun (l, [pa_tuple
(param_polymorphs +> List.map (fun (str_poly,(_,_)) ->
PaLid (l, "str__of_" ^ str_poly))),
None, body])
in
[(PaLid (l, "string_of_" ^ str), (* let string_of... *)
f_str_func_params (* str__a str__b ... *)
(ExFun(l, [(PaLid (l,"a0"), None, (* a0 = .... *)
(body_ctyp "a0" ctyp))]))) (* match a with .... *)
;(PaLid (l, "print_" ^ str),
(if param_polymorphs = []
then fun e -> e
else fun e -> (ExFun (l, [PaLid (l, "funs"), None, e]))
)
(ExFun (l, [(PaLid (l,"a")), None,
ExApp (l, ExLid (l, "print_string"),
if param_polymorphs = []
then ExApp(l, ExLid (l, "string_of_" ^ str), ExLid (l, "a"))
else ExApp (l,
ExApp (l, ExLid (l, "string_of_" ^ str),
ExLid (l, "funs")),
ExLid (l, "a")))])))
])
in
let recursif = true in
(StDcl (loc, [(StTyp (loc, tdl));StVal (loc, recursif, funcs +> List.flatten)]))
]]
;
END
;;
*)
(******************************************************************************)
(*
let gen_print_funs loc tdl =
<:str_item< not yet implemented >>
let _ =
EXTEND
Pcaml.str_item:
[ [ "type"; tdl = LIST1 Pcaml.type_declaration SEP "and" ->
let si1 = <:str_item< type $list:tdl$ >> in
let si2 = gen_print_funs loc tdl in
<:str_item< declare $si1$; $si2$; end >> ] ]
;
END
*)
(*
let fun_name n = "print_" ^ n
let fun_param_name n = "pr_" ^ n
let param_name cnt = "x" ^ string_of_int cnt
let list_mapi f l =
let rec loop cnt =
function
x :: l -> f cnt x :: loop (cnt + 1) l
| [] -> []
in
loop 1 l
let gen_print_type loc t =
let rec eot =
function
<:ctyp< $t1$ $t2$ >> -> <:expr< $eot t1$ $eot t2$ >>
| <:ctyp< $lid:s$ >> -> <:expr< $lid:fun_name s$ >>
| <:ctyp< '$s$ >> -> <:expr< $lid:fun_param_name s$ >>
| _ -> <:expr< fun _ -> print_string "..." >>
in
eot t
let gen_call loc n f = <:expr< $f$ $lid:param_name n$ >>
let gen_print_cons_patt loc c tl =
let pl =
list_mapi (fun n _ -> <:patt< $lid:param_name n$ >>)
tl
in
List.fold_left (fun p1 p2 -> <:patt< $p1$ $p2$ >>)
<:patt< $uid:c$ >> pl
let gen_print_con_extra_syntax loc el =
let rec loop =
function
[] | [_] as e -> e
| e :: el -> e :: <:expr< print_string ", " >> :: loop el
in
<:expr< print_string " (" >> :: loop el @
[<:expr< print_string ")" >>]
let gen_print_cons_expr loc c tl =
let pr_con = <:expr< print_string $str:c$ >> in
match tl with
[] -> pr_con
| _ ->
let pr_params =
let type_funs = List.map (gen_print_type loc) tl in
list_mapi (gen_call loc) type_funs
in
let pr_all = gen_print_con_extra_syntax loc pr_params in
let el = pr_con :: pr_all in
<:expr< do { $list:el$ } >>
let gen_print_cons (loc, c, tl) =
let p = gen_print_cons_patt loc c tl in
let e = gen_print_cons_expr loc c tl in
p, None, e
let gen_print_sum loc cdl =
let pwel = List.map gen_print_cons cdl in
<:expr< fun [ $list:pwel$ ] >>
let gen_one_print_fun loc ((loc, n), tpl, tk, cl) =
let body =
match tk with
<:ctyp< [ $list:cdl$ ] >> -> gen_print_sum loc cdl
| _ -> <:expr< fun _ -> failwith $str:fun_name n$ >>
in
let body =
List.fold_right
(fun (v, _) e ->
<:expr< fun $lid:fun_param_name v$ -> $e$ >>)
tpl body
in
<:patt< $lid:fun_name n$ >>, body
let gen_print_funs loc tdl =
let pel = List.map (gen_one_print_fun loc) tdl in
<:str_item< value rec $list:pel$ >>
*)
(*
let _ =
DELETE_RULE
Pcaml.str_item: "type"; LIST1 Pcaml.type_declaration SEP "and"
END;
EXTEND
Pcaml.str_item:
[ [ "type"; tdl = LIST1 Pcaml.type_declaration SEP "and" ->
let si1 = <:str_item< type $list:tdl$ >> in
let si2 = gen_print_funs loc tdl in
<:str_item< declare $si1$; $si2$; end >> ] ]
;
END
*)
(* by author of camlp4 *)
(******************************************************************************)
(*
# let expand _ s =
match s with
"PI" -> "3.14159"
| "goban" -> "19*19"
| "chess" -> "8*8"
| "ZERO" -> "0"
| "ONE" -> "1"
| _ -> "\"" ^ s ^ "\""
;;
Let us call the quotation ``foo''. We can associate the quotation ``foo'' to the above expander ``expand'' by typing:
# Quotation.add "foo" (Quotation.ExStr expand);;
We can experiment the new quotation immediately:
# <:foo<PI>>;;
- : float = 3.14159
*)
(******************************************************************************)
(*
let add_infix lev op =
EXTEND
expr: LEVEL $lev$
[ [ x = expr; $op$; y = expr -> <:expr< $lid:op$ $x$ $y$ >> ] ]
;
END;;
*)
(******************************************************************************)
(*
type term =
Var of string
| Func of string * term
| Appl of term * term
;;
The first case, Var, represents variables.
The second case, Func, represents functions. Its first parameter is the function parameter and its second parameter
the function body. We write that in concrete syntax [parameter]body.
The third case, App, represents an application of two lambda terms. We write that in concrete syntax (term1 term2).
But, for the moment, we just defined a type term, and we can just write these terms using the constructors. Here is
an example:
let id = Func ("x", Var "x")
let k = Func ("x", Func ("y", Var "x"))
let s =
Func ("x", Func ("y", Func ("z",
Appl (Appl (Var "x", Var "y"), Appl (Var "x", Var "z")))))
let delta = Func ("x", Appl (Var "x", Var "x"))
let omega = Appl (delta, delta)
A nice quotation expander would allow us to use concrete syntax. The same piece of program could look like this,
which is more readable:
let id = << [x]x >>
let k = << [x][y]x >>
let s = << [x][y][z]((x y) (x z)) >>
let delta = << [x](x x) >>
let omega = << (^delta ^delta) >>
let gram = Grammar.gcreate (Plexer.gmake ());;
let term_eoi = Grammar.Entry.create gram "term";;
let term = Grammar.Entry.create gram "term";;
EXTEND
term_eoi: [ [ x = term; EOI -> x ] ];
term:
[ [ "["; x = LIDENT; "]"; t = term -> <:expr< Func $str:x$ $t$ >>
| "("; t1 = term; t2 = term; ")" -> <:expr< Appl $t1$ $t2$ >>
| x = LIDENT -> <:expr< Var $str:x$ >> ] ]
;
END;;
let term_exp s = Grammar.Entry.parse term_eoi (Stream.of_string s);;
let term_pat s = failwith "not implemented term_pat";;
Quotation.add "term" (Quotation.ExAst (term_exp, term_pat));;
Quotation.default := "term";;
*)
(******************************************************************************)
Jump to Line
Something went wrong with that request. Please try again.