with_xxx shorthands for fold configurations

This commit is contained in:
Suzanne Dupéron 2020-04-05 20:17:55 +02:00
parent b536d3f591
commit e001154714
2 changed files with 57 additions and 45 deletions

View File

@ -143,16 +143,16 @@ say "";
for $statements -> $statement { for $statements -> $statement {
say "$statement" say "$statement"
} }
say "type 'a monad = 'a Simple_utils.Trace.result"; say "type 'a monad = 'a Simple_utils.Trace.result;;";
say "let (>>?) v f = Simple_utils.Trace.bind f v"; say "let (>>?) v f = Simple_utils.Trace.bind f v;;";
say "let return v = Simple_utils.Trace.ok v"; say "let return v = Simple_utils.Trace.ok v;;";
say "open $moduleName"; say "open $moduleName;;";
say "module Adt_info = Adt_generator.Generic.Adt_info"; say "module Adt_info = Adt_generator.Generic.Adt_info;;";
say ""; say "";
say "(* must be provided by one of the open or include statements: *)"; say "(* must be provided by one of the open or include statements: *)";
for $adts.grep({$_<kind> ne $record && $_<kind> ne $variant}).map({$_<kind>}).unique -> $poly for $adts.grep({$_<kind> ne $record && $_<kind> ne $variant}).map({$_<kind>}).unique -> $poly
{ say "let fold_map__$poly : type a new_a state . (state -> a -> (state * new_a) Simple_utils.Trace.result) -> state -> a $poly -> (state * new_a $poly) Simple_utils.Trace.result = fold_map__$poly"; } { say "let fold_map__$poly : type a new_a state . (state -> a -> (state * new_a) Simple_utils.Trace.result) -> state -> a $poly -> (state * new_a $poly) Simple_utils.Trace.result = fold_map__$poly;;"; }
say ""; say "";
for $adts.kv -> $index, $t { for $adts.kv -> $index, $t {
@ -165,6 +165,7 @@ for $adts.kv -> $index, $t {
default { say " | $c<newName> of $c<newType>" } default { say " | $c<newName> of $c<newType>" }
} }
} }
say "";
} elsif ($t<kind> eq $record) { } elsif ($t<kind> eq $record) {
say ' {'; say ' {';
for $t<ctorsOrFields>.list -> $f for $t<ctorsOrFields>.list -> $f
@ -178,6 +179,7 @@ for $adts.kv -> $index, $t {
say ""; say "";
} }
} }
say ";;";
say ""; say "";
for $adts.list -> $t { for $adts.list -> $t {
@ -185,14 +187,14 @@ for $adts.list -> $t {
say " node__$t<name> : 'state -> $t<name> -> ('state * $t<newName>) monad ;"; say " node__$t<name> : 'state -> $t<name> -> ('state * $t<newName>) monad ;";
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say " $t<name>__$c<name> : 'state -> {$c<type> || 'unit'} -> ('state * {$c<newType> || 'unit'}) monad ;" } { say " $t<name>__$c<name> : 'state -> {$c<type> || 'unit'} -> ('state * {$c<newType> || 'unit'}) monad ;" }
say ' }'; say ' };;';
} }
say "type 'state continue_fold_map = \{"; say "type 'state continue_fold_map = \{";
for $adts.list -> $t { for $adts.list -> $t {
say " $t<name> : 'state continue_fold_map__$t<name> ;"; say " $t<name> : 'state continue_fold_map__$t<name> ;";
} }
say ' }'; say ' };;';
say ""; say "";
for $adts.list -> $t for $adts.list -> $t
@ -203,24 +205,24 @@ for $adts.list -> $t
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say " $t<name>__$c<name> : 'state -> {$c<type> || 'unit'} -> 'state continue_fold_map -> ('state * {$c<newType> || 'unit'}) monad ;"; # (*Adt_info.ctor_or_field_instance_info ->*) { say " $t<name>__$c<name> : 'state -> {$c<type> || 'unit'} -> 'state continue_fold_map -> ('state * {$c<newType> || 'unit'}) monad ;"; # (*Adt_info.ctor_or_field_instance_info ->*)
} }
say '}' } say '};;' }
say "type 'state fold_map_config ="; say "type 'state fold_map_config =";
say ' {'; say ' {';
for $adts.list -> $t for $adts.list -> $t
{ say " $t<name> : 'state fold_map_config__$t<name>;" } { say " $t<name> : 'state fold_map_config__$t<name>;" }
say ' }'; say ' };;';
say ""; say "";
say "module StringMap = Map.Make(String)"; say "module StringMap = Map.Make(String);;";
say "(* generic folds for nodes *)"; say "(* generic folds for nodes *)";
say "type 'state generic_continue_fold_node = \{"; say "type 'state generic_continue_fold_node = \{";
say " continue : 'state -> 'state ;"; say " continue : 'state -> 'state ;";
say " (* generic folds for each field *)"; say " (* generic folds for each field *)";
say " continue_ctors_or_fields : ('state -> 'state) StringMap.t ;"; say " continue_ctors_or_fields : ('state -> 'state) StringMap.t ;";
say '}'; say '};;';
say "(* map from node names to their generic folds *)"; say "(* map from node names to their generic folds *)";
say "type 'state generic_continue_fold = ('state generic_continue_fold_node) StringMap.t"; say "type 'state generic_continue_fold = ('state generic_continue_fold_node) StringMap.t;;";
say ""; say "";
say "type 'state fold_config ="; say "type 'state fold_config =";
say ' {'; say ' {';
@ -231,7 +233,7 @@ for $adts.map({ $_<ctorsOrFields> })[*;*].grep({$_<isBuiltin> && $_<type> ne ''}
# look for built-in polymorphic types # look for built-in polymorphic types
for $adts.grep({$_<kind> ne $record && $_<kind> ne $variant}).map({$_<kind>}).unique -> $poly for $adts.grep({$_<kind> ne $record && $_<kind> ne $variant}).map({$_<kind>}).unique -> $poly
{ say " $poly : 'a . 'state fold_config -> ('state -> 'a -> 'state) -> 'state -> 'a $poly -> 'state;"; } { say " $poly : 'a . 'state fold_config -> ('state -> 'a -> 'state) -> 'state -> 'a $poly -> 'state;"; }
say ' }'; say ' };;';
say ""; say "";
say 'type blahblah = {'; say 'type blahblah = {';
@ -239,7 +241,7 @@ for $adts.list -> $t
{ say " fold__$t<name> : 'state . blahblah -> 'state fold_config -> 'state -> $t<name> -> 'state;"; { say " fold__$t<name> : 'state . blahblah -> 'state fold_config -> 'state -> $t<name> -> 'state;";
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say " fold__$t<name>__$c<name> : 'state . blahblah -> 'state fold_config -> 'state -> { $c<type> || 'unit' } -> 'state;"; } } { say " fold__$t<name>__$c<name> : 'state . blahblah -> 'state fold_config -> 'state -> { $c<type> || 'unit' } -> 'state;"; } }
say '}'; say '};;';
# generic programming info about the nodes and fields # generic programming info about the nodes and fields
say ""; say "";
@ -255,7 +257,7 @@ for $adts.list -> $t
say "let continue_info__$t<name>__$c<name> : type qstate . blahblah -> qstate fold_config -> {$c<type> || 'unit'} -> qstate Adt_info.ctor_or_field_instance = fun blahblah visitor x -> \{"; say "let continue_info__$t<name>__$c<name> : type qstate . blahblah -> qstate fold_config -> {$c<type> || 'unit'} -> qstate Adt_info.ctor_or_field_instance = fun blahblah visitor x -> \{";
say " cf = info__$t<name>__$c<name>;"; say " cf = info__$t<name>__$c<name>;";
say " cf_continue = fun state -> blahblah.fold__$t<name>__$c<name> blahblah visitor state x;"; say " cf_continue = fun state -> blahblah.fold__$t<name>__$c<name> blahblah visitor state x;";
say '}'; say '};;';
say ""; } say ""; }
say "(* info for node $t<name> *)"; say "(* info for node $t<name> *)";
say "let info__$t<name> : Adt_info.node = \{"; say "let info__$t<name> : Adt_info.node = \{";
@ -269,7 +271,7 @@ for $adts.list -> $t
print " ctors_or_fields = [ "; print " ctors_or_fields = [ ";
for $t<ctorsOrFields>.list -> $c { print "info__$t<name>__$c<name> ; "; } for $t<ctorsOrFields>.list -> $c { print "info__$t<name>__$c<name> ; "; }
say "];"; say "];";
say '}'; say '};;';
say ""; say "";
# TODO: factor out some of the common bits here. # TODO: factor out some of the common bits here.
say "let continue_info__$t<name> : type qstate . blahblah -> qstate fold_config -> $t<name> -> qstate Adt_info.instance = fun blahblah visitor x ->"; say "let continue_info__$t<name> : type qstate . blahblah -> qstate fold_config -> $t<name> -> qstate Adt_info.instance = fun blahblah visitor x ->";
@ -309,7 +311,7 @@ for $adts.list -> $t
say '};'; say '};';
} }
}; };
say '}'; say '};;';
say ""; } say ""; }
say ""; say "";
@ -317,7 +319,7 @@ say "(* info for adt $moduleName *)";
print "let whole_adt_info : unit -> Adt_info.adt = fun () -> [ "; print "let whole_adt_info : unit -> Adt_info.adt = fun () -> [ ";
for $adts.list -> $t for $adts.list -> $t
{ print "info__$t<name> ; "; } { print "info__$t<name> ; "; }
say "]"; say "];;";
# fold functions # fold functions
say ""; say "";
@ -329,18 +331,18 @@ for $adts.list -> $t
say " node_instance = continue_info__$t<name> blahblah visitor x"; say " node_instance = continue_info__$t<name> blahblah visitor x";
say ' } in'; say ' } in';
# say " let (state, new_x) = visitor.$t<name>.node__$t<name> x (fun () -> whole_adt_info, info__$t<name>) state continue_fold in"; # say " let (state, new_x) = visitor.$t<name>.node__$t<name> x (fun () -> whole_adt_info, info__$t<name>) state continue_fold in";
say " visitor.generic state node_instance_info"; say " visitor.generic state node_instance_info;;";
say ""; say "";
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say "let fold__$t<name>__$c<name> : type qstate . blahblah -> qstate fold_config -> qstate -> { $c<type> || 'unit' } -> qstate = fun blahblah { $c<type> ?? 'visitor' !! '_visitor' } state { $c<type> ?? 'x' !! '()' } ->"; { say "let fold__$t<name>__$c<name> : type qstate . blahblah -> qstate fold_config -> qstate -> { $c<type> || 'unit' } -> qstate = fun blahblah { $c<type> ?? 'visitor' !! '_visitor' } state { $c<type> ?? 'x' !! '()' } ->";
# say " let ctor_or_field_instance_info : qstate Adt_info.ctor_or_field_instance_info = whole_adt_info (), info__$t<name>, continue_info__$t<name>__$c<name> visitor x in"; # say " let ctor_or_field_instance_info : qstate Adt_info.ctor_or_field_instance_info = whole_adt_info (), info__$t<name>, continue_info__$t<name>__$c<name> visitor x in";
if ($c<type> eq '') { if ($c<type> eq '') {
# nothing to do, this constructor has no arguments. # nothing to do, this constructor has no arguments.
say " ignore blahblah; state"; say " ignore blahblah; state;;";
} elsif ($c<isBuiltin>) { } elsif ($c<isBuiltin>) {
say " ignore blahblah; visitor.$c<type> visitor state x"; # (*visitor.generic_ctor_or_field ctor_or_field_instance_info*) say " ignore blahblah; visitor.$c<type> visitor state x;;"; # (*visitor.generic_ctor_or_field ctor_or_field_instance_info*)
} else { } else {
say " blahblah.fold__$c<type> blahblah visitor state x"; # (*visitor.generic_ctor_or_field ctor_or_field_instance_info*) say " blahblah.fold__$c<type> blahblah visitor state x;;"; # (*visitor.generic_ctor_or_field ctor_or_field_instance_info*)
} }
# say " visitor.$t<name>.$t<name>__$c<name> x (fun () -> whole_adt_info, info__$t<name>, info__$t<name>__$c<name>) state continue_fold"; # say " visitor.$t<name>.$t<name>__$c<name> x (fun () -> whole_adt_info, info__$t<name>, info__$t<name>__$c<name>) state continue_fold";
say ""; } say ""; }
@ -352,20 +354,20 @@ for $adts.list -> $t
{ say " fold__$t<name>;"; { say " fold__$t<name>;";
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say " fold__$t<name>__$c<name>;" } } { say " fold__$t<name>__$c<name>;" } }
say '}'; say '};;';
# Tying the knot # Tying the knot
say ""; say "";
for $adts.list -> $t for $adts.list -> $t
{ say "let fold__$t<name> : type qstate . qstate fold_config -> qstate -> $t<name> -> qstate = fun visitor state x -> fold__$t<name> blahblah visitor state x"; { say "let fold__$t<name> : type qstate . qstate fold_config -> qstate -> $t<name> -> qstate = fun visitor state x -> fold__$t<name> blahblah visitor state x;;";
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say "let fold__$t<name>__$c<name> : type qstate . qstate fold_config -> qstate -> { $c<type> || 'unit' } -> qstate = fun visitor state x -> fold__$t<name>__$c<name> blahblah visitor state x" } } { say "let fold__$t<name>__$c<name> : type qstate . qstate fold_config -> qstate -> { $c<type> || 'unit' } -> qstate = fun visitor state x -> fold__$t<name>__$c<name> blahblah visitor state x;;" } }
say ""; say "";
say "type 'state mk_continue_fold_map = \{"; say "type 'state mk_continue_fold_map = \{";
say " fn : 'state mk_continue_fold_map -> 'state fold_map_config -> 'state continue_fold_map"; say " fn : 'state mk_continue_fold_map -> 'state fold_map_config -> 'state continue_fold_map";
say '}'; say '};;';
# fold_map functions # fold_map functions
@ -376,12 +378,12 @@ for $adts.list -> $t
say " visitor.$t<name>.node__$t<name>__pre_state state x >>? fun state ->"; # (*(fun () -> whole_adt_info, info__$t<name>)*) say " visitor.$t<name>.node__$t<name>__pre_state state x >>? fun state ->"; # (*(fun () -> whole_adt_info, info__$t<name>)*)
say " visitor.$t<name>.node__$t<name> state x continue_fold_map >>? fun (state, new_x) ->"; # (*(fun () -> whole_adt_info, info__$t<name>)*) say " visitor.$t<name>.node__$t<name> state x continue_fold_map >>? fun (state, new_x) ->"; # (*(fun () -> whole_adt_info, info__$t<name>)*)
say " visitor.$t<name>.node__$t<name>__post_state state x new_x >>? fun state ->"; # (*(fun () -> whole_adt_info, info__$t<name>)*) say " visitor.$t<name>.node__$t<name>__post_state state x new_x >>? fun state ->"; # (*(fun () -> whole_adt_info, info__$t<name>)*)
say " return (state, new_x)"; say " return (state, new_x);;";
say ""; say "";
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say "let _fold_map__$t<name>__$c<name> : type qstate . qstate mk_continue_fold_map -> qstate fold_map_config -> qstate -> { $c<type> || 'unit' } -> (qstate * { $c<newType> || 'unit' }) monad = fun mk_continue_fold_map visitor state x ->"; { say "let _fold_map__$t<name>__$c<name> : type qstate . qstate mk_continue_fold_map -> qstate fold_map_config -> qstate -> { $c<type> || 'unit' } -> (qstate * { $c<newType> || 'unit' }) monad = fun mk_continue_fold_map visitor state x ->";
say " let continue_fold_map : qstate continue_fold_map = mk_continue_fold_map.fn mk_continue_fold_map visitor in"; say " let continue_fold_map : qstate continue_fold_map = mk_continue_fold_map.fn mk_continue_fold_map visitor in";
say " visitor.$t<name>.$t<name>__$c<name> state x continue_fold_map"; # (*(fun () -> whole_adt_info, info__$t<name>, info__$t<name>__$c<name>)*) say " visitor.$t<name>.$t<name>__$c<name> state x continue_fold_map;;"; # (*(fun () -> whole_adt_info, info__$t<name>, info__$t<name>__$c<name>)*)
say ""; } } say ""; } }
# make the "continue" object # make the "continue" object
@ -396,17 +398,17 @@ for $adts.list -> $t
{ say " $t<name>__$c<name> = (fun state x -> _fold_map__$t<name>__$c<name> self visitor state x) ;"; } { say " $t<name>__$c<name> = (fun state x -> _fold_map__$t<name>__$c<name> self visitor state x) ;"; }
say ' };' } say ' };' }
say ' }'; say ' }';
say '}'; say '};;';
say ""; say "";
# fold_map functions : tying the knot # fold_map functions : tying the knot
say ""; say "";
for $adts.list -> $t for $adts.list -> $t
{ say "let fold_map__$t<name> : type qstate . qstate fold_map_config -> qstate -> $t<name> -> (qstate * $t<newName>) monad ="; { say "let fold_map__$t<name> : type qstate . qstate fold_map_config -> qstate -> $t<name> -> (qstate * $t<newName>) monad =";
say " fun visitor state x -> _fold_map__$t<name> mk_continue_fold_map visitor state x"; say " fun visitor state x -> _fold_map__$t<name> mk_continue_fold_map visitor state x;;";
for $t<ctorsOrFields>.list -> $c for $t<ctorsOrFields>.list -> $c
{ say "let fold_map__$t<name>__$c<name> : type qstate . qstate fold_map_config -> qstate -> { $c<type> || 'unit' } -> (qstate * { $c<newType> || 'unit' }) monad ="; { say "let fold_map__$t<name>__$c<name> : type qstate . qstate fold_map_config -> qstate -> { $c<type> || 'unit' } -> (qstate * { $c<newType> || 'unit' }) monad =";
say " fun visitor state x -> _fold_map__$t<name>__$c<name> mk_continue_fold_map visitor state x"; } } say " fun visitor state x -> _fold_map__$t<name>__$c<name> mk_continue_fold_map visitor state x;;"; } }
for $adts.list -> $t for $adts.list -> $t
@ -433,7 +435,7 @@ for $adts.list -> $t
} else { } else {
print " v -> fold_map__$t<kind> ( "; print " v -> fold_map__$t<kind> ( ";
print ( "continue.$t<name>.$t<name>__$_<name>" for $t<ctorsOrFields>.list ).join(", "); print ( "continue.$t<name>.$t<name>__$_<name>" for $t<ctorsOrFields>.list ).join(", ");
say " ) state v"; say " ) state v;;";
} }
} }
@ -455,4 +457,12 @@ for $adts.list -> $t
say "let no_op : type state . state fold_map_config = \{"; say "let no_op : type state . state fold_map_config = \{";
for $adts.list -> $t for $adts.list -> $t
{ say " $t<name> = no_op__$t<name>;" } { say " $t<name> = no_op__$t<name>;" }
say '}'; say '};;';
say "";
for $adts.list -> $t
{ say "let with__$t<name> : _ = (fun node__$t<name> op -> \{ op with $t<name> = \{ op.$t<name> with node__$t<name> \} \});;";
say "let with__$t<name>__pre_state : _ = (fun node__$t<name>__pre_state op -> \{ op with $t<name> = \{ op.$t<name> with node__$t<name>__pre_state \} \});;";
say "let with__$t<name>__post_state : _ = (fun node__$t<name>__post_state op -> \{ op with $t<name> = \{ op.$t<name> with node__$t<name>__post_state \} \});;";
for $t<ctorsOrFields>.list -> $c
{ say "let with__$t<name>__$c<name> : _ = (fun $t<name>__$c<name> op -> \{ op with $t<name> = \{ op.$t<name> with $t<name>__$c<name> \} \});;"; } }

View File

@ -2,6 +2,8 @@ open Amodule
open Fold open Fold
open Simple_utils.Trace open Simple_utils.Trace
let (|>) v f = f v
module Errors = struct module Errors = struct
let test_fail msg = let test_fail msg =
let title () = "test failed" in let title () = "test failed" in
@ -17,14 +19,13 @@ let test (x : unit result) : unit = match x with
let () = let () =
test @@ test @@
let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in
let op = { let op =
no_op with no_op |>
a = { no_op.a with with__a (fun state the_a (*_info*) continue_fold ->
node__a = fun state the_a (*_info*) continue_fold -> let%bind state, a1__' = continue_fold.ta1.node__ta1 state the_a.a1 in
let%bind state, a1__' = continue_fold.ta1.node__ta1 state the_a.a1 in let%bind state, a2__' = continue_fold.ta2.node__ta2 state the_a.a2 in
let%bind state, a2__' = continue_fold.ta2.node__ta2 state the_a.a2 in ok (state + 1, { a1__' ; a2__' }))
ok (state + 1, { a1__' ; a2__' }) } in
} in
let state = 0 in let state = 0 in
let%bind (state , _) = fold_map__root op state some_root in let%bind (state , _) = fold_map__root op state some_root in
if state != 2 then if state != 2 then
@ -35,7 +36,8 @@ let () =
let () = let () =
test @@ test @@
let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in
let op = { no_op with a = { no_op.a with node__a__pre_state = fun state _the_a (*_info*) -> ok @@ state + 1 } } in let op = no_op |>
with__a__pre_state (fun state _the_a (*_info*) -> ok @@ state + 1) in
let state = 0 in let state = 0 in
let%bind (state , _) = fold_map__root op state some_root in let%bind (state , _) = fold_map__root op state some_root in
if state != 2 then if state != 2 then
@ -46,7 +48,7 @@ let () =
let () = let () =
test @@ test @@
let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in let some_root : root = A [{ a1 = X (A [{ a1 = X (B [1;2;3]) ; a2 = W () ; }]) ; a2 = Z (W ()) ; }] in
let op = { no_op with a = { no_op.a with node__a__post_state = fun state _the_a _new_a (*_info*) -> ok @@ state + 1 } } in let op = no_op |> with__a__post_state (fun state _the_a _new_a (*_info*) -> ok @@ state + 1) in
let state = 0 in let state = 0 in
let%bind (state , _) = fold_map__root op state some_root in let%bind (state , _) = fold_map__root op state some_root in
if state != 2 then if state != 2 then
@ -75,7 +77,7 @@ let () =
| false, arg -> true, name ^ " " ^ arg) | false, arg -> true, name ^ " " ^ arg)
| PolyInstance { poly=_; arguments=_; poly_continue } -> | PolyInstance { poly=_; arguments=_; poly_continue } ->
(poly_continue nostate) (poly_continue nostate)
); ) ;
string = (fun _visitor state str -> assert_nostate state; false , "\"" ^ str ^ "\"") ; string = (fun _visitor state str -> assert_nostate state; false , "\"" ^ str ^ "\"") ;
unit = (fun _visitor state () -> assert_nostate state; false , "()") ; unit = (fun _visitor state () -> assert_nostate state; false , "()") ;
int = (fun _visitor state i -> assert_nostate state; false , string_of_int i) ; int = (fun _visitor state i -> assert_nostate state; false , string_of_int i) ;