diff --git a/docker/distribution/generic/build.Dockerfile b/docker/distribution/generic/build.Dockerfile index f6c9358e9..ba01c043c 100644 --- a/docker/distribution/generic/build.Dockerfile +++ b/docker/distribution/generic/build.Dockerfile @@ -29,7 +29,7 @@ RUN opam update # Install ligo RUN sh scripts/install_vendors_deps.sh -RUN opam install -y . +RUN opam install -y . || (tail -n +1 ~/.opam/log/* ; false) # Use the ligo binary as a default command ENTRYPOINT [ "/home/opam/.opam/4.07/bin/ligo" ] diff --git a/scripts/build_docker_image.sh b/scripts/build_docker_image.sh index 3934417a9..b39bdc22a 100755 --- a/scripts/build_docker_image.sh +++ b/scripts/build_docker_image.sh @@ -1,5 +1,6 @@ #!/bin/sh set -e +set -x if test $# -ne 1 || test "x$1" = "-h" -o "x$1" = "x--help"; then echo "Usage: build_docker_image.sh TAG_NAME" diff --git a/scripts/build_ligo_local.sh b/scripts/build_ligo_local.sh index b78e4ffd6..fb556805a 100755 --- a/scripts/build_ligo_local.sh +++ b/scripts/build_ligo_local.sh @@ -1,5 +1,6 @@ #!/bin/sh set -e +set -x eval $(opam config env) dune build -p ligo diff --git a/scripts/distribution/generic/build.sh b/scripts/distribution/generic/build.sh index 49aba15e1..968f55a21 100755 --- a/scripts/distribution/generic/build.sh +++ b/scripts/distribution/generic/build.sh @@ -1,4 +1,6 @@ #!/bin/sh +set -e +set -x dockerfile_name="build" # Generic dockerfile diff --git a/scripts/distribution/generic/package.sh b/scripts/distribution/generic/package.sh index 79be37d41..d9d047e6d 100755 --- a/scripts/distribution/generic/package.sh +++ b/scripts/distribution/generic/package.sh @@ -1,4 +1,6 @@ #!/bin/sh +set -e +set -x dockerfile_name="package" dockerfile="" diff --git a/scripts/distribution/generic/parameters.sh b/scripts/distribution/generic/parameters.sh index 3899711d8..2241b9fb0 100644 --- a/scripts/distribution/generic/parameters.sh +++ b/scripts/distribution/generic/parameters.sh @@ -1,11 +1,15 @@ +#!/bin/sh +set -e +set -x + # This script accepts three arguments, os family, os and its version, # which are subsequently used to fetch the respective docker # image from the ocaml/infrastructure project. # # https://github.com/ocaml/infrastructure/wiki/Containers#selecting-linux-distributions -target_os_family=$1 -target_os=$2 -target_os_version=$3 +target_os_family="$1" +target_os="$2" +target_os_version="$3" # Variables configured at the CI level dist="$LIGO_DIST_DIR" @@ -29,4 +33,4 @@ fi target_os_specific_dockerfile="./docker/distribution/$target_os_family/$target_os/$dockerfile_name.Dockerfile" if test -f "$target_os_specific_dockerfile"; then dockerfile="$target_os_specific_dockerfile" -fi \ No newline at end of file +fi diff --git a/scripts/install_build_environment.sh b/scripts/install_build_environment.sh index 0dd33f068..7a52cf684 100755 --- a/scripts/install_build_environment.sh +++ b/scripts/install_build_environment.sh @@ -22,26 +22,29 @@ echo "Installing dependencies.." if [ -n "`uname -a | grep -i arch`" ] then sudo pacman -Sy --noconfirm \ + rakudo \ make \ m4 \ gcc \ patch \ bubblewrap \ rsync \ - curl + curl fi if [ -n "`uname -a | grep -i ubuntu`" ] then sudo apt-get install -y make \ + perl6 \ + make \ m4 \ gcc \ patch \ bubblewrap \ rsync \ - curl + curl fi - + if [ -n "`uname -a | grep -i ubuntu`" ] then echo "ubuntu" diff --git a/scripts/install_native_dependencies.sh b/scripts/install_native_dependencies.sh index 2a0e56903..9156cd823 100755 --- a/scripts/install_native_dependencies.sh +++ b/scripts/install_native_dependencies.sh @@ -1,11 +1,13 @@ #!/bin/sh set -e +set -x . /etc/os-release if [ $ID = arch ] then pacman -Sy sudo pacman -S --noconfirm \ + rakudo \ libevdev \ perl \ pkg-config \ @@ -20,6 +22,7 @@ then else apt-get update -qq apt-get -y -qq install \ + perl6 \ libev-dev \ perl \ pkg-config \ diff --git a/scripts/install_vendors_deps.sh b/scripts/install_vendors_deps.sh index 15f9b47d4..5c870ffdc 100755 --- a/scripts/install_vendors_deps.sh +++ b/scripts/install_vendors_deps.sh @@ -1,5 +1,6 @@ #!/bin/sh set -e +set -x # Install local dependencies opam install -y --deps-only --with-test ./ligo.opam $(find vendors -name \*.opam) diff --git a/src/passes/8-typer-old/typer.ml b/src/passes/8-typer-old/typer.ml index b94a51475..b75508477 100644 --- a/src/passes/8-typer-old/typer.ml +++ b/src/passes/8-typer-old/typer.ml @@ -567,7 +567,6 @@ and type_expression' : environment -> ?tv_opt:O.type_expression -> I.expression let wtype = Format.asprintf "Loops over collections expect lists, sets or maps, got type %a" O.PP.type_expression tv_col in fail @@ simple_error wtype in - let lname = lname in let e' = Environment.add_ez_binder lname input_type e in let%bind body = type_expression' ?tv_opt:(Some tv_out) e' result in let output_type = body.type_expression in diff --git a/src/stages/4-ast_typed/types.ml b/src/stages/4-ast_typed/types.ml index b406c46b7..e267ff03c 100644 --- a/src/stages/4-ast_typed/types.ml +++ b/src/stages/4-ast_typed/types.ml @@ -106,7 +106,6 @@ and ascription = { type_annotation: type_expression ; } - and environment_element_definition = | ED_binder | ED_declaration of environment_element_definition_declaration diff --git a/src/stages/adt_generator/.gitignore b/src/stages/adt_generator/.gitignore new file mode 100644 index 000000000..9ec2ad34e --- /dev/null +++ b/src/stages/adt_generator/.gitignore @@ -0,0 +1,2 @@ +# This is an auto-generated test file +/generated_fold.ml diff --git a/src/stages/adt_generator/README b/src/stages/adt_generator/README index 20ecdfd43..2463bd663 100644 --- a/src/stages/adt_generator/README +++ b/src/stages/adt_generator/README @@ -1,7 +1,7 @@ -Build with: +Build & test with: - dune build adt_generator.a + dune build adt_generator.exe && ../../../_build/default/src/stages/adt_generator/adt_generator.exe Run with - python ./generator.py + perl6 ./generator.raku amodule.ml diff --git a/src/stages/adt_generator/adt_generator.ml b/src/stages/adt_generator/adt_generator.ml index 9c1ff4b88..840fe1b02 100644 --- a/src/stages/adt_generator/adt_generator.ml +++ b/src/stages/adt_generator/adt_generator.ml @@ -1,2 +1,2 @@ -module A = A +module Amodule = Amodule module Use_a_fold = Use_a_fold diff --git a/src/stages/adt_generator/a.ml b/src/stages/adt_generator/amodule.ml similarity index 66% rename from src/stages/adt_generator/a.ml rename to src/stages/adt_generator/amodule.ml index f1d8b2fb1..8de6bdb5e 100644 --- a/src/stages/adt_generator/a.ml +++ b/src/stages/adt_generator/amodule.ml @@ -1,6 +1,6 @@ type root = -| A of a -| B of int +| A of rootA +| B of rootB | C of string and a = { @@ -15,3 +15,7 @@ and ta1 = and ta2 = | Z of ta2 | W of unit + +and rootA = a list + +and rootB = int list diff --git a/src/stages/adt_generator/amodule_utils.ml b/src/stages/adt_generator/amodule_utils.ml new file mode 100644 index 000000000..0e3855bb8 --- /dev/null +++ b/src/stages/adt_generator/amodule_utils.ml @@ -0,0 +1,10 @@ +let fold_map_list v state continue = + let aux = fun (lst', state) elt -> + let (elt', state) = continue elt state in + (elt' :: lst' , state) in + List.fold_left aux ([], state) v + +let fold_map_option v state continue = + match v with + Some x -> continue x state + | None -> None diff --git a/src/stages/adt_generator/dune b/src/stages/adt_generator/dune index 4a52c6088..88b963a4d 100644 --- a/src/stages/adt_generator/dune +++ b/src/stages/adt_generator/dune @@ -1,8 +1,9 @@ (rule - (target fold.ml) - (deps generator.py) - (action (with-stdout-to fold.ml (run python3 ./generator.py))) - (mode (promote (until-clean)))) + (target generated_fold.ml) + (deps generator.raku) + (action (with-stdout-to generated_fold.ml (run perl6 ./generator.raku amodule.ml))) +; (mode (promote (until-clean))) +) ; (library ; (name adt_generator) ; (public_name ligo.adt_generator) @@ -16,3 +17,8 @@ (libraries ) ) + +(alias + (name runtest) + (action (run ./adt_generator.exe)) +) diff --git a/src/stages/adt_generator/fold.ml b/src/stages/adt_generator/fold.ml index 4e4c41357..271974820 100644 --- a/src/stages/adt_generator/fold.ml +++ b/src/stages/adt_generator/fold.ml @@ -1,184 +1 @@ -open A - -type root' = - | A' of a' - | B' of int - | C' of string -and a' = - { - a1' : ta1' ; - a2' : ta2' ; - } -and ta1' = - | X' of root' - | Y' of ta2' -and ta2' = - | Z' of ta2' - | W' of unit - -type 'state continue_fold = - { - root : root -> 'state -> (root' * 'state) ; - root_A : a -> 'state -> (a' * 'state) ; - root_B : int -> 'state -> (int * 'state) ; - root_C : string -> 'state -> (string * 'state) ; - a : a -> 'state -> (a' * 'state) ; - a_a1 : ta1 -> 'state -> (ta1' * 'state) ; - a_a2 : ta2 -> 'state -> (ta2' * 'state) ; - ta1 : ta1 -> 'state -> (ta1' * 'state) ; - ta1_X : root -> 'state -> (root' * 'state) ; - ta1_Y : ta2 -> 'state -> (ta2' * 'state) ; - ta2 : ta2 -> 'state -> (ta2' * 'state) ; - ta2_Z : ta2 -> 'state -> (ta2' * 'state) ; - ta2_W : unit -> 'state -> (unit * 'state) ; - } - -type 'state fold_config = - { - root : root -> 'state -> ('state continue_fold) -> (root' * 'state) ; - root_pre_state : root -> 'state -> 'state ; - root_post_state : root -> root' -> 'state -> 'state ; - root_A : a -> 'state -> ('state continue_fold) -> (a' * 'state) ; - root_B : int -> 'state -> ('state continue_fold) -> (int * 'state) ; - root_C : string -> 'state -> ('state continue_fold) -> (string * 'state) ; - a : a -> 'state -> ('state continue_fold) -> (a' * 'state) ; - a_pre_state : a -> 'state -> 'state ; - a_post_state : a -> a' -> 'state -> 'state ; - a_a1 : ta1 -> 'state -> ('state continue_fold) -> (ta1' * 'state) ; - a_a2 : ta2 -> 'state -> ('state continue_fold) -> (ta2' * 'state) ; - ta1 : ta1 -> 'state -> ('state continue_fold) -> (ta1' * 'state) ; - ta1_pre_state : ta1 -> 'state -> 'state ; - ta1_post_state : ta1 -> ta1' -> 'state -> 'state ; - ta1_X : root -> 'state -> ('state continue_fold) -> (root' * 'state) ; - ta1_Y : ta2 -> 'state -> ('state continue_fold) -> (ta2' * 'state) ; - ta2 : ta2 -> 'state -> ('state continue_fold) -> (ta2' * 'state) ; - ta2_pre_state : ta2 -> 'state -> 'state ; - ta2_post_state : ta2 -> ta2' -> 'state -> 'state ; - ta2_Z : ta2 -> 'state -> ('state continue_fold) -> (ta2' * 'state) ; - ta2_W : unit -> 'state -> ('state continue_fold) -> (unit * 'state) ; - } - -(* Curries the "visitor" argument to the folds (non-customizable traversal functions). *) -let rec mk_continue_fold : type state . state fold_config -> state continue_fold = fun visitor -> - { - root = fold_root visitor ; - root_A = fold_root_A visitor ; - root_B = fold_root_B visitor ; - root_C = fold_root_C visitor ; - a = fold_a visitor ; - a_a1 = fold_a_a1 visitor ; - a_a2 = fold_a_a2 visitor ; - ta1 = fold_ta1 visitor ; - ta1_X = fold_ta1_X visitor ; - ta1_Y = fold_ta1_Y visitor ; - ta2 = fold_ta2 visitor ; - ta2_Z = fold_ta2_Z visitor ; - ta2_W = fold_ta2_W visitor ; -} - -and fold_root : type state . state fold_config -> root -> state -> (root' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - let state = visitor.root_pre_state x state in - let (new_x, state) = visitor.root x state continue_fold in - let state = visitor.root_post_state x new_x state in - (new_x, state) - -and fold_root_A : type state . state fold_config -> a -> state -> (a' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.root_A x state continue_fold - -and fold_root_B : type state . state fold_config -> int -> state -> (int * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.root_B x state continue_fold - -and fold_root_C : type state . state fold_config -> string -> state -> (string * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.root_C x state continue_fold - -and fold_a : type state . state fold_config -> a -> state -> (a' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - let state = visitor.a_pre_state x state in - let (new_x, state) = visitor.a x state continue_fold in - let state = visitor.a_post_state x new_x state in - (new_x, state) - -and fold_a_a1 : type state . state fold_config -> ta1 -> state -> (ta1' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.a_a1 x state continue_fold - -and fold_a_a2 : type state . state fold_config -> ta2 -> state -> (ta2' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.a_a2 x state continue_fold - -and fold_ta1 : type state . state fold_config -> ta1 -> state -> (ta1' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - let state = visitor.ta1_pre_state x state in - let (new_x, state) = visitor.ta1 x state continue_fold in - let state = visitor.ta1_post_state x new_x state in - (new_x, state) - -and fold_ta1_X : type state . state fold_config -> root -> state -> (root' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.ta1_X x state continue_fold - -and fold_ta1_Y : type state . state fold_config -> ta2 -> state -> (ta2' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.ta1_Y x state continue_fold - -and fold_ta2 : type state . state fold_config -> ta2 -> state -> (ta2' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - let state = visitor.ta2_pre_state x state in - let (new_x, state) = visitor.ta2 x state continue_fold in - let state = visitor.ta2_post_state x new_x state in - (new_x, state) - -and fold_ta2_Z : type state . state fold_config -> ta2 -> state -> (ta2' * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.ta2_Z x state continue_fold - -and fold_ta2_W : type state . state fold_config -> unit -> state -> (unit * state) = fun visitor x state -> - let continue_fold : state continue_fold = mk_continue_fold visitor in - visitor.ta2_W x state continue_fold - -let no_op : 'a fold_config = { - root = (fun v state continue -> - match v with - | A v -> let (v, state) = continue.root_A v state in (A' v, state) - | B v -> let (v, state) = continue.root_B v state in (B' v, state) - | C v -> let (v, state) = continue.root_C v state in (C' v, state) - ); - root_pre_state = (fun v state -> ignore v; state) ; - root_post_state = (fun v new_v state -> ignore (v, new_v); state) ; - root_A = (fun v state continue -> continue.a v state ) ; - root_B = (fun v state continue -> ignore continue; (v, state) ) ; - root_C = (fun v state continue -> ignore continue; (v, state) ) ; - a = (fun v state continue -> - match v with - { a1; a2; } -> - let (a1', state) = continue.a_a1 a1 state in - let (a2', state) = continue.a_a2 a2 state in - ({ a1'; a2'; }, state) - ); - a_pre_state = (fun v state -> ignore v; state) ; - a_post_state = (fun v new_v state -> ignore (v, new_v); state) ; - a_a1 = (fun v state continue -> continue.ta1 v state ) ; - a_a2 = (fun v state continue -> continue.ta2 v state ) ; - ta1 = (fun v state continue -> - match v with - | X v -> let (v, state) = continue.ta1_X v state in (X' v, state) - | Y v -> let (v, state) = continue.ta1_Y v state in (Y' v, state) - ); - ta1_pre_state = (fun v state -> ignore v; state) ; - ta1_post_state = (fun v new_v state -> ignore (v, new_v); state) ; - ta1_X = (fun v state continue -> continue.root v state ) ; - ta1_Y = (fun v state continue -> continue.ta2 v state ) ; - ta2 = (fun v state continue -> - match v with - | Z v -> let (v, state) = continue.ta2_Z v state in (Z' v, state) - | W v -> let (v, state) = continue.ta2_W v state in (W' v, state) - ); - ta2_pre_state = (fun v state -> ignore v; state) ; - ta2_post_state = (fun v new_v state -> ignore (v, new_v); state) ; - ta2_Z = (fun v state continue -> continue.ta2 v state ) ; - ta2_W = (fun v state continue -> ignore continue; (v, state) ) ; -} +include Generated_fold diff --git a/src/stages/adt_generator/generator.pl b/src/stages/adt_generator/generator.pl new file mode 100644 index 000000000..c145a5b4b --- /dev/null +++ b/src/stages/adt_generator/generator.pl @@ -0,0 +1,212 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use 5.010; +use Data::Dumper; $Data::Dumper::Useqq = 1; # use double quotes when dumping (we have a few "prime'" names) +sub enumerate { my $i = 0; [map { [ $i++, $_ ] } @{$_[0]}] } + +my $moduleName = "A"; +my $variant = "_ _variant"; +my $record = "_ _ record"; my $true = 1; my $false = 0; +sub poly { $_[0] } +my $adts_raw = [ + # typename, kind, fields_or_ctors + ["root", $variant, [ + # ctor, builtin?, type + ["A", $false, "rootA"], + ["B", $false, "rootB"], + ["C", $true, "string"], + ]], + ["a", $record, [ + # field, builtin?, type + ["a1", $false, "ta1"], + ["a2", $false, "ta2"], + ]], + ["ta1", $variant, [ + ["X", $false, "root"], + ["Y", $false, "ta2"], + ]], + ["ta2", $variant, [ + ["Z", $false, "ta2"], + ["W", $true, "unit"], + ]], + # polymorphic type + ["rootA", poly("list"), + [ + # Position (0..n-1), builtin?, type argument + [0, $false, "a"] + ]], + ["rootB", poly("list"), + [ + # Position (0..n-1), builtin?, type argument + [0, $true, "int"] + ]], + ]; + + + + +my $adts = [map { + my ($name , $kind, $ctorsOrFields) = @$_; + { + "name" => $name , + "newName" => "${name}'" , + "kind" => $kind , + "ctorsOrFields" => [map { + my ($cf, $isBuiltin, $type) = @$_; + { + name => $cf , + newName => "${cf}'" , + isBuiltin => $isBuiltin , + type => $type , + newType => $isBuiltin ? $type : "${type}'" + } + } @$ctorsOrFields], + } +} @$adts_raw]; + +# print Dumper $adts ; + +say "(* This is an auto-generated file. Do not edit. *)"; + +say ""; +say "open ${moduleName}"; + +say ""; +foreach (@{enumerate($adts)}) { + my ($index, $t) = @$_; + my %t = %$t; + my $typeOrAnd = $index == 0 ? "type" : "and"; + say "${typeOrAnd} $t{newName} ="; + if ($t{kind} eq $variant) { + foreach (@{$t{ctorsOrFields}}) { + my %c = %$_; + say " | $c{newName} of $c{newType}" + } + } + elsif ($t{kind} eq $record) { + say " {"; + foreach (@{$t{ctorsOrFields}}) { + my %f = %$_; + say " $f{newName} : $f{newType} ;"; + } + say " }"; + } else { + print " "; + foreach (@{$t{ctorsOrFields}}) { + my %a = %$_; + print "$a{newType} "; + } + print "$t{kind}"; + say ""; + } +} + +say ""; +say "type 'state continue_fold ="; +say " {"; +foreach (@$adts) { + my %t = %$_; + say " $t{name} : $t{name} -> 'state -> ($t{newName} * 'state) ;"; + foreach (@{$t{ctorsOrFields}}) { + my %c = %$_; + say " $t{name}_$c{name} : $c{type} -> 'state -> ($c{newType} * 'state) ;" + } +} +say " }"; + +say ""; +say "type 'state fold_config ="; +say " {"; +foreach (@$adts) { + my %t = %$_; + say " $t{name} : $t{name} -> 'state -> ('state continue_fold) -> ($t{newName} * 'state) ;"; + say " $t{name}_pre_state : $t{name} -> 'state -> 'state ;"; + say " $t{name}_post_state : $t{name} -> $t{newName} -> 'state -> 'state ;"; + foreach (@{$t{ctorsOrFields}}) { + my %c = %$_; + say " $t{name}_$c{name} : $c{type} -> 'state -> ('state continue_fold) -> ($c{newType} * 'state) ;"; + } +} +say " }"; + +say ""; +say '(* Curries the "visitor" argument to the folds (non-customizable traversal functions). *)'; +say "let rec mk_continue_fold : type state . state fold_config -> state continue_fold = fun visitor ->"; +say " {"; +foreach (@$adts) { + my %t = %$_; + say " $t{name} = fold_$t{name} visitor ;"; + foreach (@{$t{ctorsOrFields}}) { + my %c = %$_; + say " $t{name}_$c{name} = fold_$t{name}_$c{name} visitor ;"; + } +} +say "}"; +say ""; + +foreach (@$adts) { + my %t = %$_; + say "and fold_$t{name} : type state . state fold_config -> $t{name} -> state -> ($t{newName} * state) = fun visitor x state ->"; + say " let continue_fold : state continue_fold = mk_continue_fold visitor in"; + say " let state = visitor.$t{name}_pre_state x state in"; + say " let (new_x, state) = visitor.$t{name} x state continue_fold in"; + say " let state = visitor.$t{name}_post_state x new_x state in"; + say " (new_x, state)"; + say ""; + foreach (@{$t{ctorsOrFields}}) { + my %c = %$_; + say "and fold_$t{name}_$c{name} : type state . state fold_config -> $c{type} -> state -> ($c{newType} * state) = fun visitor x state ->"; + say " let continue_fold : state continue_fold = mk_continue_fold visitor in"; + say " visitor.$t{name}_$c{name} x state continue_fold"; + say ""; + } +} + +say "let no_op : 'a fold_config = {"; +foreach (@$adts) { + my %t = %$_; + say " $t{name} = (fun v state continue ->"; + say " match v with"; + if ($t{kind} eq $variant) { + foreach (@{$t{ctorsOrFields}}) { + my %c = %$_; + say " | $c{name} v -> let (v, state) = continue.$t{name}_$c{name} v state in ($c{newName} v, state)"; + } + } elsif ($t{kind} eq $record) { + print " { "; + foreach (@{$t{ctorsOrFields}}) { + my %f = %$_; + print "$f{name}; "; + } + say "} ->"; + foreach (@{$t{ctorsOrFields}}) { + my %f = %$_; + say " let ($f{newName}, state) = continue.$t{name}_$f{name} $f{name} state in"; + } + print " ({ "; + foreach (@{$t{ctorsOrFields}}) { + my %f = %$_; + print "$f{newName}; " + } + say "}, state)"; + } else { + print " v -> fold_$t{kind} v state ( "; + print join(", ", map { my %f = %$_; "continue.$t{name}_$f{name}" } @{$t{ctorsOrFields}}); + say " )"; + } + say " );"; + say " $t{name}_pre_state = (fun v state -> ignore v; state) ;"; + say " $t{name}_post_state = (fun v new_v state -> ignore (v, new_v); state) ;"; + foreach (@{$t{ctorsOrFields}}) { + my %c = %$_; + print " $t{name}_$c{name} = (fun v state continue -> "; + if ($c{isBuiltin}) { + print "ignore continue; (v, state)"; + } else { + print "continue.$c{type} v state"; + } + say ") ;"; + } +} +say "}"; diff --git a/src/stages/adt_generator/generator.py b/src/stages/adt_generator/generator.py index 65fe21878..e4af0468a 100644 --- a/src/stages/adt_generator/generator.py +++ b/src/stages/adt_generator/generator.py @@ -1,34 +1,56 @@ +#!/usr/bin/env python3 +import pprint + + + + + moduleName = "A" +variant="_ _variant" +record="_ _record" +def poly(x): return x adts = [ - # typename, variant?, fields_or_ctors - ("root", True, [ - # ctor, builtin, type - ("A", False, "a"), - ("B", True, "int"), + # typename, kind, fields_or_ctors + ("root", variant, [ + # ctor, builtin?, type + ("A", False, "rootA"), + ("B", False, "rootB"), ("C", True, "string"), ]), - ("a", False, [ + ("a", record, [ + # field, builtin?, type ("a1", False, "ta1"), ("a2", False, "ta2"), ]), - ("ta1", True, [ + ("ta1", variant, [ ("X", False, "root"), ("Y", False, "ta2"), ]), - ("ta2", True, [ + ("ta2", variant, [ ("Z", False, "ta2"), ("W", True, "unit"), ]), + # polymorphic type + ("rootA", poly("list"), + [ + # Position (0..n-1), builtin?, type argument + (0, False, "a") + ]), + ("rootB", poly("list"), + [ + # Position (0..n-1), builtin?, type argument + (0, True, "int") + ]), ] from collections import namedtuple -adt = namedtuple('adt', ['name', 'newName', 'isVariant', 'ctorsOrFields']) +adt = namedtuple('adt', ['name', 'newName', 'kind', 'ctorsOrFields']) ctorOrField = namedtuple('ctorOrField', ['name', 'newName', 'isBuiltin', 'type_', 'newType']) adts = [ adt( name = name, newName = f"{name}'", - isVariant = isVariant, + kind = kind, ctorsOrFields = [ ctorOrField( name = cf, @@ -40,23 +62,34 @@ adts = [ for (cf, isBuiltin, type_) in ctors ], ) - for (name, isVariant, ctors) in adts + for (name, kind, ctors) in adts ] +# pprint.PrettyPrinter(compact=False, indent=4).pprint(adts) + +print("(* This is an auto-generated file. Do not edit. *)") + +print("") print("open %s" % moduleName) print("") for (index, t) in enumerate(adts): typeOrAnd = "type" if index == 0 else "and" print(f"{typeOrAnd} {t.newName} =") - if t.isVariant: + if t.kind == variant: for c in t.ctorsOrFields: print(f" | {c.newName} of {c.newType}") - else: + elif t.kind == record: print(" {") for f in t.ctorsOrFields: print(f" {f.newName} : {f.newType} ;") print(" }") + else: + print(" ", end='') + for a in t.ctorsOrFields: + print(f"{a.newType}", end=' ') + print(t.kind, end='') + print("") print("") print(f"type 'state continue_fold =") @@ -107,10 +140,10 @@ print("let no_op : 'a fold_config = {") for t in adts: print(f" {t.name} = (fun v state continue ->") print(" match v with") - if t.isVariant: + if t.kind == variant: for c in t.ctorsOrFields: print(f" | {c.name} v -> let (v, state) = continue.{t.name}_{c.name} v state in ({c.newName} v, state)") - else: + elif t.kind == record: print(" {", end=' ') for f in t.ctorsOrFields: print(f"{f.name};", end=' ') @@ -121,14 +154,18 @@ for t in adts: for f in t.ctorsOrFields: print(f"{f.newName};", end=' ') print("}, state)") + else: + print(f" v -> fold_{t.kind} v state (", end=' ') + print(", ".join([f"continue.{t.name}_{f.name}" for f in t.ctorsOrFields]), end='') + print(" )") print(" );") print(f" {t.name}_pre_state = (fun v state -> ignore v; state) ;") print(f" {t.name}_post_state = (fun v new_v state -> ignore (v, new_v); state) ;") for c in t.ctorsOrFields: print(f" {t.name}_{c.name} = (fun v state continue ->", end=' ') if c.isBuiltin: - print("ignore continue; (v, state)", end=' ') + print("ignore continue; (v, state)", end='') else: - print(f"continue.{c.type_} v state", end=' ') + print(f"continue.{c.type_} v state", end='') print(") ;") print("}") diff --git a/src/stages/adt_generator/generator.raku b/src/stages/adt_generator/generator.raku new file mode 100644 index 000000000..71ab1286e --- /dev/null +++ b/src/stages/adt_generator/generator.raku @@ -0,0 +1,364 @@ +#!/usr/bin/env perl6 +use v6.c; +use strict; +use worries; + +my $moduleName = @*ARGS[0].subst(/\.ml$/, '').samecase("A_"); +my $variant = "_ _variant"; +my $record = "_ _ record"; +sub poly { $^type_name } + +my $l = @*ARGS[0].IO.lines; +$l = $l.map(*.subst: /^\s+/, ""); +$l = $l.cache.map(*.subst: /^type\s+/, "\nand "); +$l = $l.join("\n").split(/\nand\s+/).grep(/./); +$l = $l.map(*.split("\n")); +$l = $l.map: { + my $ll = $_; + my ($name, $kind) = do given $_[0] { + when /^(\w+)\s*\=$/ { "$/[0]", $variant } + when /^(\w+)\s*\=\s*\{$/ { "$/[0]", $record } + when /^(\w+)\s*\=\s*(\w+)\s+(\w+)$/ { "$/[0]", poly("$/[2]") } + default { die "Syntax error when parsing header:" ~ $ll.perl ~ "\n$_" } + }; + my $ctorsOrFields = do { + when (/^(\w+)\s*\=\s*(\w+)\s+(\w+)$/ given $_[0]) { ((0, "$/[1]"),).Seq; } + default { + $_[1..*].grep({ ! /^\}?$/ }).map: { + when /^\|\s*(\w+)\s*of\s+((\'|\w)+)$/ { "$/[0]", "$/[1]" } + when /^(\w+)\s*\:\s*((\'|\w)+)\s*\;$/ { "$/[0]", "$/[1]" } + default { die "Syntax error when parsing body:" ~ $ll.perl ~ "\n$_" } + } + }; + } + %{ + "name" => $name , + "kind" => $kind , + "ctorsOrFields" => $ctorsOrFields + } + # $_[0].subst: , '' } +}; +# $l.perl.say; +# exit; + +# ($cf, $isBuiltin, $type) + # { + # name => $cf , + # newName => "$cf'" , + # isBuiltin => $isBuiltin , + # type => $type , + # newType => $isBuiltin ?? $type !! "$type'" + # } + + + +# my @adts_raw = [ +# # typename, kind, fields_or_ctors +# ["root", $variant, [ +# # ctor, builtin?, type +# ["A", False, "rootA"], +# ["B", False, "rootB"], +# ["C", True, "string"], +# ]], +# ["a", $record, [ +# # field, builtin?, type +# ["a1", False, "ta1"], +# ["a2", False, "ta2"], +# ]], +# ["ta1", $variant, [ +# ["X", False, "root"], +# ["Y", False, "ta2"], +# ]], +# ["ta2", $variant, [ +# ["Z", False, "ta2"], +# ["W", True, "unit"], +# ]], +# # polymorphic type +# ["rootA", poly("list"), +# [ +# # Position (0..n-1), builtin?, type argument +# [0, False, "a"], +# ], +# ], +# ["rootB", poly("list"), +# [ +# # Position (0..n-1), builtin?, type argument +# [0, True, "int"], +# ], +# ], +# ]; + +# # say $adts_raw.perl; +# my $adts = (map -> ($name , $kind, @ctorsOrFields) { +# { +# "name" => $name , +# "newName" => "$name'" , +# "kind" => $kind , +# "ctorsOrFields" => @(map -> ($cf, $isBuiltin, $type) { +# { +# name => $cf , +# newName => "$cf'" , +# isBuiltin => $isBuiltin , +# type => $type , +# newType => $isBuiltin ?? $type !! "$type'" +# } +# }, @ctorsOrFields), +# } +# }, @adts_raw).list; + +my $adts = (map -> (:$name , :$kind, :@ctorsOrFields) { + { + "name" => $name , + "newName" => "$name'" , + "kind" => $kind , + "ctorsOrFields" => @(map -> ($cf, $type) { + my $isBuiltin = ! $l.cache.first({ $_ eq $type }); + { + name => $cf , + newName => "$cf'" , + isBuiltin => $isBuiltin , + type => $type , + newType => $isBuiltin ?? $type !! "$type'" + } + }, @ctorsOrFields), + } +}, @$l.cache).list; + +# say $adts.perl; + +# say $adts.perl ; + +say "(* This is an auto-generated file. Do not edit. *)"; + +say ""; +say "open $moduleName"; +say "open {$moduleName}_utils"; +say "module Adt_info = Generic.Adt_info"; + +say ""; +for $adts.kv -> $index, $t { + my $typeOrAnd = $index == 0 ?? "type" !! "and"; + say "$typeOrAnd $t ="; + if ($t eq $variant) { + for $t.list -> $c + { say " | $c of $c" } + } elsif ($t eq $record) { + say ' {'; + for $t.list -> $f + { say " $f : $f ;"; } + say ' }'; + } else { + print " "; + for $t.list -> $a + { print "$a "; } + print "$t"; + say ""; + } +} + +say ""; +say "type 'state continue_fold_map ="; +say ' {'; +for $adts.list -> $t +{ say " $t : $t -> 'state -> ($t * 'state) ;"; + for $t.list -> $c + { say " $t_$c : $c -> 'state -> ($c * 'state) ;" } } +say ' }'; + +say ""; +say "type 'state fold_map_config ="; +say ' {'; +for $adts.list -> $t +{ say " $t : $t -> (*Adt_info.node_instance_info ->*) 'state -> ('state continue_fold_map) -> ($t * 'state) ;"; + say " $t_pre_state : $t -> (*Adt_info.node_instance_info ->*) 'state -> 'state ;"; + say " $t_post_state : $t -> $t -> (*Adt_info.node_instance_info ->*) 'state -> 'state ;"; + for $t.list -> $c + { say " $t_$c : $c -> (*Adt_info.ctor_or_field_instance_info ->*) 'state -> ('state continue_fold_map) -> ($c * 'state) ;"; + } } +say ' }'; + +say ""; +say "module StringMap = Map.Make(String)"; +say "(* generic folds for nodes *)"; +say "type 'state generic_continue_fold_node = \{"; +say " continue : 'state -> 'state ;"; +say " (* generic folds for each field *)"; +say " continue_ctors_or_fields : ('state -> 'state) StringMap.t ;"; +say '}'; +say "(* map from node names to their generic folds *)"; +say "type 'state generic_continue_fold = ('state generic_continue_fold_node) StringMap.t"; +say ""; +say "type 'state fold_config ="; +say ' {'; +say " generic : 'state Adt_info.node_instance_info -> 'state -> 'state;"; +for $adts.map({ $_ })[*;*].grep({$_}).map({$_}).unique -> $builtin +{ say " $builtin : 'state fold_config -> $builtin -> 'state -> 'state;"; } +for $adts.grep({$_ ne $record && $_ ne $variant}).map({$_}).unique -> $builtin +{ say " $builtin : 'a . 'state fold_config -> 'a $builtin -> ('state -> 'a -> 'state) -> 'state -> 'state;"; } +say ' }'; +say "(* info for adt $moduleName *)"; +print "let rec whole_adt_info : unit -> Adt_info.adt = fun () -> [ "; +for $adts.list -> $t +{ print "info_$t ; "; } +say "]"; + +# generic programming info about the nodes and fields +say ""; +for $adts.list -> $t +{ for $t.list -> $c + { say "(* info for field or ctor $t.$c *)"; + say "and info_$t_$c : Adt_info.ctor_or_field = \{"; + say " name = \"$c\";"; + say " is_builtin = {$c ?? 'true' !! 'false'};"; + say " type_ = \"$c\";"; + say '}'; + say ""; + say "and continue_info_$t_$c : type qstate . qstate fold_config -> $c -> qstate Adt_info.ctor_or_field_instance = fun visitor x -> \{"; + say " cf = info_$t_$c;"; + say " cf_continue = fun state -> fold_$t_$c visitor x state;"; + say '}'; + say ""; } + say "(* info for node $t *)"; + say "and info_$t : Adt_info.node = \{"; + my $kind = do given $t { + when $record { "Record" } + when $variant { "Variant" } + default { "Poly \"$_\"" } + }; + say " kind = $kind;"; + say " declaration_name = \"$t\";"; + print " ctors_or_fields = [ "; + for $t.list -> $c { print "info_$t_$c ; "; } + say "];"; + say '}'; + say ""; + # TODO: factor out some of the common bits here. + say "and continue_info_$t : type qstate . qstate fold_config -> $t -> qstate Adt_info.instance = fun visitor x ->"; + say '{'; + say " instance_declaration_name = \"$t\";"; + do given $t { + when $record { + say ' instance_kind = RecordInstance {'; + print " fields = [ "; + for $t.list -> $c { print "continue_info_$t_$c visitor x.$c ; "; } + say " ];"; + say '};'; + } + when $variant { + say ' instance_kind = VariantInstance {'; + say " constructor = (match x with"; + for $t.list -> $c { say " | $c v -> continue_info_$t_$c visitor v"; } + say " );"; + print " variant = [ "; + for $t.list -> $c { print "info_$t_$c ; "; } + say "];"; + say '};'; + } + default { + say ' instance_kind = PolyInstance {'; + say " poly = \"$_\";"; + print " arguments = ["; + # TODO: sort by c (currently we only have one-argument + # polymorphic types so it happens to work but should be fixed. + for $t.list -> $c { print "\"$c\""; } + say "];"; + print " poly_continue = (fun state -> visitor.$_ visitor x ("; + print $t + .map(-> $c { "(fun state x -> (continue_info_$t_$c visitor x).cf_continue state)" }) + .join(", "); + say ") state);"; + say '};'; + } + }; + say '}'; + say ""; } + +# make the "continue" object +say ""; +say '(* Curries the "visitor" argument to the folds (non-customizable traversal functions). *)'; +say "and mk_continue_fold_map : type qstate . qstate fold_map_config -> qstate continue_fold_map = fun visitor ->"; +say ' {'; +for $adts.list -> $t +{ say " $t = fold_map_$t visitor ;"; + for $t.list -> $c + { say " $t_$c = fold_map_$t_$c visitor ;"; } } +say ' }'; +say ""; + +# fold_map functions +say ""; +for $adts.list -> $t +{ say "and fold_map_$t : type qstate . qstate fold_map_config -> $t -> qstate -> ($t * qstate) = fun visitor x state ->"; + say " let continue_fold_map : qstate continue_fold_map = mk_continue_fold_map visitor in"; + say " let state = visitor.$t_pre_state x (*(fun () -> whole_adt_info, info_$t)*) state in"; + say " let (new_x, state) = visitor.$t x (*(fun () -> whole_adt_info, info_$t)*) state continue_fold_map in"; + say " let state = visitor.$t_post_state x new_x (*(fun () -> whole_adt_info, info_$t)*) state in"; + say " (new_x, state)"; + say ""; + for $t.list -> $c + { say "and fold_map_$t_$c : type qstate . qstate fold_map_config -> $c -> qstate -> ($c * qstate) = fun visitor x state ->"; + say " let continue_fold_map : qstate continue_fold_map = mk_continue_fold_map visitor in"; + say " visitor.$t_$c x (*(fun () -> whole_adt_info, info_$t, info_$t_$c)*) state continue_fold_map"; + say ""; } } + + +# fold functions +say ""; +for $adts.list -> $t +{ say "and fold_$t : type qstate . qstate fold_config -> $t -> qstate -> qstate = fun visitor x state ->"; + # TODO: add a non-generic continue_fold. + say ' let node_instance_info : qstate Adt_info.node_instance_info = {'; + say " adt = whole_adt_info () ;"; + say " node_instance = continue_info_$t visitor x"; + say ' } in'; + # say " let (new_x, state) = visitor.$t x (fun () -> whole_adt_info, info_$t) state continue_fold in"; + say " visitor.generic node_instance_info state"; + say ""; + for $t.list -> $c + { say "and fold_$t_$c : type qstate . qstate fold_config -> $c -> qstate -> qstate = fun visitor x state ->"; + # say " let ctor_or_field_instance_info : qstate Adt_info.ctor_or_field_instance_info = whole_adt_info (), info_$t, continue_info_$t_$c visitor x in"; + if ($c) { + say " let state = (*visitor.generic_ctor_or_field ctor_or_field_instance_info*) visitor.$c visitor x state in"; + } else { + say " let state = (*visitor.generic_ctor_or_field ctor_or_field_instance_info*) fold_$c visitor x state in"; + } + say " state"; + # say " visitor.$t_$c x (fun () -> whole_adt_info, info_$t, info_$t_$c) state continue_fold"; + say ""; } +} + +say "let no_op : 'a fold_map_config = \{"; +for $adts.list -> $t +{ say " $t = (fun v (*_info*) state continue ->"; + say " match v with"; + if ($t eq $variant) { + for $t.list -> $c + { say " | $c v -> let (v, state) = continue.$t_$c v state in ($c v, state)"; } + } elsif ($t eq $record) { + print ' { '; + for $t.list -> $f + { print "$f; "; } + say "} ->"; + for $t.list -> $f + { say " let ($f, state) = continue.$t_$f $f state in"; } + print ' ({ '; + for $t.list -> $f + { print "$f; "; } + say '}, state)'; + } else { + print " v -> fold_map_$t v state ( "; + print ( "continue.$t_$_" for $t.list ).join(", "); + say " )"; + } + say " );"; + say " $t_pre_state = (fun v (*_info*) state -> ignore v; state) ;"; + say " $t_post_state = (fun v new_v (*_info*) state -> ignore (v, new_v); state) ;"; + for $t.list -> $c + { print " $t_$c = (fun v (*_info*) state continue -> "; + if ($c) { + print "ignore continue; (v, state)"; + } else { + print "continue.$c v state"; + } + say ") ;"; } } +say '}'; diff --git a/src/stages/adt_generator/generic.ml b/src/stages/adt_generator/generic.ml new file mode 100644 index 000000000..7defcfbb2 --- /dev/null +++ b/src/stages/adt_generator/generic.ml @@ -0,0 +1,59 @@ +module Adt_info = struct + type kind = + | Record + | Variant + | Poly of string + + type 'state record_instance = { + fields : 'state ctor_or_field_instance list; + } + + and 'state constructor_instance = { + constructor : 'state ctor_or_field_instance ; + variant : ctor_or_field list + } + + and 'state poly_instance = { + poly : string; + arguments : string list; + poly_continue : 'state -> 'state + } + + and 'state kind_instance = + | RecordInstance of 'state record_instance + | VariantInstance of 'state constructor_instance + | PolyInstance of 'state poly_instance + + and 'state instance = { + instance_declaration_name : string; + instance_kind : 'state kind_instance; + } + + and ctor_or_field = + { + name : string; + is_builtin : bool; + type_ : string; + } + + and 'state ctor_or_field_instance = + { + cf : ctor_or_field; + cf_continue : 'state -> 'state + } + + type node = + { + kind : kind; + declaration_name : string; + ctors_or_fields : ctor_or_field list; + } + + (* TODO: rename things a bit in this file. *) + type adt = node list + type 'state node_instance_info = { + adt : adt ; + node_instance : 'state instance ; + } + type 'state ctor_or_field_instance_info = adt * node * 'state ctor_or_field_instance +end diff --git a/src/stages/adt_generator/use_a_fold.ml b/src/stages/adt_generator/use_a_fold.ml index 6a73f4782..c62c38e0f 100644 --- a/src/stages/adt_generator/use_a_fold.ml +++ b/src/stages/adt_generator/use_a_fold.ml @@ -1,13 +1,13 @@ -open A +open Amodule open Fold (* TODO: how should we plug these into our test framework? *) let () = - let some_root : root = A { a1 = X (A { a1 = X (B 1) ; 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 = fun the_a state continue_fold -> + a = fun the_a (*_info*) state continue_fold -> let (a1' , state') = continue_fold.ta1 the_a.a1 state in let (a2' , state'') = continue_fold.ta2 the_a.a2 state' in ({ @@ -16,33 +16,68 @@ let () = }, state'' + 1) } in let state = 0 in - let (_, state) = fold_root op some_root state in + let (_, state) = fold_map_root op some_root state in if state != 2 then failwith (Printf.sprintf "Test failed: expected folder to count 2 nodes, but it counted %d nodes" state) else () let () = - let some_root : root = A { a1 = X (A { a1 = X (B 1) ; a2 = W () ; }) ; a2 = Z (W ()) ; } in - let op = { no_op with a_pre_state = fun _the_a state -> state + 1 } 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_pre_state = fun _the_a (*_info*) state -> state + 1 } in let state = 0 in - let (_, state) = fold_root op some_root state in + let (_, state) = fold_map_root op some_root state in if state != 2 then failwith (Printf.sprintf "Test failed: expected folder to count 2 nodes, but it counted %d nodes" state) else () let () = - let some_root : root = A { a1 = X (A { a1 = X (B 1) ; a2 = W () ; }) ; a2 = Z (W ()) ; } in - let op = { no_op with a_post_state = fun _the_a _new_a state -> state + 1 } 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_post_state = fun _the_a _new_a (*_info*) state -> state + 1 } in let state = 0 in - let (_, state) = fold_root op some_root state in + let (_, state) = fold_map_root op some_root state in if state != 2 then failwith (Printf.sprintf "Test failed: expected folder to count 2 nodes, but it counted %d nodes" state) else () -(* Test that the same fold_config can be ascibed with different 'a type arguments *) -let _noi : int fold_config = no_op (* (fun _ -> ()) *) -let _nob : bool fold_config = no_op (* (fun _ -> ()) *) +(* Test that the same fold_map_config can be ascibed with different 'a type arguments *) +let _noi : int fold_map_config = no_op (* (fun _ -> ()) *) +let _nob : bool fold_map_config = no_op (* (fun _ -> ()) *) + +let () = + let some_root : root = A [ { a1 = X (A [ { a1 = X (B [ 1 ; 2 ; 3 ]) ; a2 = W () } ]) ; a2 = Z (W ()) } ] in + let assert_nostate (needs_parens, state) = assert (not needs_parens && String.equal state "") in + let nostate = false, "" in + let op = { + generic = (fun info state -> + assert_nostate state; + match info.node_instance.instance_kind with + | RecordInstance { fields } -> + false, "{ " ^ String.concat " ; " (List.map (fun (fld : 'x Adt_info.ctor_or_field_instance) -> fld.cf.name ^ " = " ^ snd (fld.cf_continue nostate)) fields) ^ " }" + | VariantInstance { constructor={ cf = { name; is_builtin=_; type_=_ }; cf_continue }; variant=_ } -> + (match cf_continue nostate with + | true, arg -> true, name ^ " (" ^ arg ^ ")" + | false, arg -> true, name ^ " " ^ arg) + | PolyInstance { poly=_; arguments=_; poly_continue } -> + (poly_continue nostate) + ); + string = (fun _visitor str state -> assert_nostate state; false , "\"" ^ str ^ "\"") ; + unit = (fun _visitor () state -> assert_nostate state; false , "()") ; + int = (fun _visitor i state -> assert_nostate state; false , string_of_int i) ; + list = (fun _visitor lst continue state -> + assert_nostate state; + false , "[ " ^ String.concat " ; " (List.map snd @@ List.map (continue nostate) lst) ^ " ]") ; + (* generic_ctor_or_field = (fun _info state -> + * match _info () with + * (_, _, { name=_; isBuiltin=_; type_=_; continue }) -> state ^ "ctor_or_field [" ^ (continue "") ^ "]" + * ); *) + } in + let (_ , state) = fold_root op some_root nostate in + let expected = "A [ { a1 = X (A [ { a1 = X (B [ 1 ; 2 ; 3 ]) ; a2 = W () } ]) ; a2 = Z (W ()) } ]" in + if String.equal state expected; then + () + else + failwith (Printf.sprintf "Test failed: expected\n %s\n but got\n %s" expected state) diff --git a/tools/webide/Dockerfile b/tools/webide/Dockerfile index cf259c68c..166432acb 100644 --- a/tools/webide/Dockerfile +++ b/tools/webide/Dockerfile @@ -21,7 +21,7 @@ FROM node:12-buster WORKDIR /app -RUN apt-get update && apt-get -y install libev-dev perl pkg-config libgmp-dev libhidapi-dev m4 libcap-dev bubblewrap rsync +RUN apt-get update && apt-get -y install perl6 libev-dev perl pkg-config libgmp-dev libhidapi-dev m4 libcap-dev bubblewrap rsync COPY ligo_deb10.deb /tmp/ligo_deb10.deb RUN dpkg -i /tmp/ligo_deb10.deb && rm /tmp/ligo_deb10.deb diff --git a/vendors/UnionFind/UnionFind.install b/vendors/UnionFind/UnionFind.install deleted file mode 100644 index cc7a1853e..000000000 --- a/vendors/UnionFind/UnionFind.install +++ /dev/null @@ -1,40 +0,0 @@ -lib: [ - "_build/install/default/lib/UnionFind/META" - "_build/install/default/lib/UnionFind/Partition.mli" - "_build/install/default/lib/UnionFind/Partition0.ml" - "_build/install/default/lib/UnionFind/Partition1.ml" - "_build/install/default/lib/UnionFind/Partition2.ml" - "_build/install/default/lib/UnionFind/Partition3.ml" - "_build/install/default/lib/UnionFind/UnionFind.a" - "_build/install/default/lib/UnionFind/UnionFind.cma" - "_build/install/default/lib/UnionFind/UnionFind.cmxa" - "_build/install/default/lib/UnionFind/UnionFind.cmxs" - "_build/install/default/lib/UnionFind/dune-package" - "_build/install/default/lib/UnionFind/opam" - "_build/install/default/lib/UnionFind/unionFind.cmi" - "_build/install/default/lib/UnionFind/unionFind.cmt" - "_build/install/default/lib/UnionFind/unionFind.cmx" - "_build/install/default/lib/UnionFind/unionFind.ml" - "_build/install/default/lib/UnionFind/unionFind__.cmi" - "_build/install/default/lib/UnionFind/unionFind__.cmt" - "_build/install/default/lib/UnionFind/unionFind__.cmx" - "_build/install/default/lib/UnionFind/unionFind__.ml" - "_build/install/default/lib/UnionFind/unionFind__Partition.cmi" - "_build/install/default/lib/UnionFind/unionFind__Partition.cmti" - "_build/install/default/lib/UnionFind/unionFind__Partition0.cmi" - "_build/install/default/lib/UnionFind/unionFind__Partition0.cmt" - "_build/install/default/lib/UnionFind/unionFind__Partition0.cmx" - "_build/install/default/lib/UnionFind/unionFind__Partition1.cmi" - "_build/install/default/lib/UnionFind/unionFind__Partition1.cmt" - "_build/install/default/lib/UnionFind/unionFind__Partition1.cmx" - "_build/install/default/lib/UnionFind/unionFind__Partition2.cmi" - "_build/install/default/lib/UnionFind/unionFind__Partition2.cmt" - "_build/install/default/lib/UnionFind/unionFind__Partition2.cmx" - "_build/install/default/lib/UnionFind/unionFind__Partition3.cmi" - "_build/install/default/lib/UnionFind/unionFind__Partition3.cmt" - "_build/install/default/lib/UnionFind/unionFind__Partition3.cmx" -] -doc: [ - "_build/install/default/doc/UnionFind/LICENSE" - "_build/install/default/doc/UnionFind/README.md" -]