Merge branch 'dev' into 'feature/doc-pascaligo-loop'

# Conflicts:
#   src/passes/operators/operators.ml
This commit is contained in:
Suzanne Dupéron 2020-02-10 20:51:41 +00:00
commit 0113a448de
77 changed files with 969 additions and 1149 deletions

View File

@ -40,6 +40,7 @@ dont-merge-to-master:
- build-and-package-ubuntu-18-04
- build-and-package-ubuntu-19-04
before_script:
- export TERM=dumb
- scripts/install_native_dependencies.sh
- scripts/install_opam.sh # TODO: or scripts/install_build_environment.sh ?
- export PATH="/usr/local/bin${PATH:+:}${PATH:-}"
@ -86,6 +87,7 @@ dont-merge-to-master:
before_script:
# Install dependencies
# rsync is needed by opam to sync a package installed from a local directory with the copy in ~/.opam
- export TERM=dumb
- scripts/install_native_dependencies.sh
- scripts/install_opam.sh # TODO: or scripts/install_build_environment.sh ?
- export PATH="/usr/local/bin${PATH:+:}${PATH:-}"

View File

@ -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" ]

View File

@ -1,3 +1,4 @@
#!/bin/sh
set -e
docker build -t "${LIGO_REGISTRY_IMAGE_BUILD:-ligolang/ligo}:next" -f ./docker/distribution/debian/distribute.Dockerfile .
set -x
docker build -t "${LIGO_REGISTRY_IMAGE_BUILD:-ligolang/ligo}:next" -f ./docker/distribution/debian/distribute.Dockerfile .

View File

@ -1,5 +1,6 @@
#!/bin/sh
set -e
set -x
eval $(opam config env)
dune build -p ligo

View File

@ -1,4 +1,6 @@
#!/bin/sh
set -e
set -x
dockerfile_name="build"
# Generic dockerfile

View File

@ -1,4 +1,6 @@
#!/bin/sh
set -e
set -x
dockerfile_name="package"
dockerfile=""

View File

@ -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
fi

View File

@ -22,6 +22,7 @@ echo "Installing dependencies.."
if [ -n "`uname -a | grep -i arch`" ]
then
sudo pacman -Sy --noconfirm \
python \
make \
m4 \
gcc \
@ -34,6 +35,8 @@ fi
if [ -n "`uname -a | grep -i ubuntu`" ]
then
sudo apt-get install -y make \
python3 \
make \
m4 \
gcc \
patch \

View File

@ -1,11 +1,13 @@
#!/bin/sh
set -e
set -x
. /etc/os-release
if [ $ID = arch ]
then
pacman -Sy
sudo pacman -S --noconfirm \
python \
libevdev \
perl \
pkg-config \
@ -20,6 +22,7 @@ then
else
apt-get update -qq
apt-get -y -qq install \
python3 \
libev-dev \
perl \
pkg-config \

View File

@ -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)

2
scripts/installer.sh Executable file → Normal file
View File

@ -62,7 +62,7 @@ else
# && redirect the output of the wget download to the temporary file
# ) || clean up temporary file if any command in the previous block failed
wget "$url" -O - \
(wget "$url" -O - 2>/dev/null || echo "ERROR: wget $url failed.") \
| sed -e "s/next/$version/g" \
| sudo sh -c ' \
( \

View File

@ -1079,7 +1079,7 @@ let%expect_test _ =
let%expect_test _ =
run_ligo_bad [ "compile-contract" ; contract "bad_timestamp.ligo" ; "main" ] ;
[%expect {|
ligo: in file "bad_timestamp.ligo", line 5, characters 29-43. Badly formatted timestamp "badtimestamp": {"location":"in file \"bad_timestamp.ligo\", line 5, characters 29-43"}
ligo: in file "bad_timestamp.ligo", line 7, characters 30-44. Badly formatted timestamp "badtimestamp": {"location":"in file \"bad_timestamp.ligo\", line 7, characters 30-44"}
If you're not sure how to fix this error, you can

View File

@ -649,7 +649,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

2
src/stages/adt_generator/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# This is an auto-generated test file
/generated_fold.ml

View File

@ -1,6 +1,6 @@
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

View File

@ -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,20 @@ and ta1 =
and ta2 =
| Z of ta2
| W of unit
and rootA =
a list
and rootB =
int list
let fold_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_option v state continue =
match v with
Some x -> continue x state
| None -> None

View File

@ -1,8 +1,9 @@
(rule
(target fold.ml)
(target generated_fold.ml)
(deps generator.py)
(action (with-stdout-to fold.ml (run python3 ./generator.py)))
(mode (promote (until-clean))))
(action (with-stdout-to generated_fold.ml (run python3 ./generator.py)))
; (mode (promote (until-clean))) ; If this is uncommented, then "dune build -p ligo" can't find the file (but "dune build" can)
)
; (library
; (name adt_generator)
; (public_name ligo.adt_generator)
@ -16,3 +17,8 @@
(libraries
)
)
(alias
(name runtest)
(action (run ./adt_generator.exe))
)

View File

@ -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

View File

@ -1,34 +1,49 @@
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 +55,32 @@ adts = [
for (cf, isBuiltin, type_) in ctors
],
)
for (name, isVariant, ctors) in adts
for (name, kind, ctors) in 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 +131,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,6 +145,10 @@ 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) ;")

View File

@ -4,7 +4,7 @@ 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 ->
@ -23,7 +23,7 @@ let () =
()
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_pre_state = fun _the_a state -> state + 1 } in
let state = 0 in
let (_, state) = fold_root op some_root state in
@ -33,7 +33,7 @@ let () =
()
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_post_state = fun _the_a _new_a state -> state + 1 } in
let state = 0 in
let (_, state) = fold_root op some_root state in

View File

@ -95,7 +95,6 @@ and matching =
and ascription = {anno_expr: expression; type_annotation: type_expression}
and environment_element_definition =
| ED_binder
| ED_declaration of (expression * free_variables)

View File

@ -1,5 +1,5 @@
// function main (const c: contract(unit)) : address is address(c)
// function main (const c : contract (unit)) : address is address (c)
function main (const p : key_hash) : address is block {
const c : contract(unit) = implicit_account(p) ;
} with address(c)
const c : contract (unit) = implicit_account (p);
} with address (c)

View File

@ -1,6 +1,6 @@
(* Test that a string is cast to an address given a type annotation *)
const lst : list(int) = list []
const lst : list (int) = list []
const my_address : address =
("tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx" : address)

View File

@ -1,21 +1,13 @@
// Test different ways of calling functions in PascaLIGO
type foo is record
bar : int -> int ;
end
type foo is record [bar : int -> int]
function f (const i : int) : int is
begin
skip
end with i
function f (const i : int) : int is i
function g (const i : unit) : int -> int is
begin skip end with f
function g (const i : unit) : int -> int is f
const r : foo = record
bar = f ;
end
const r : foo = record [bar = f]
const x : int = f(42)
const y : int = r.bar(42)
const z : int = (g(unit))(42)
const x : int = f (42)
const y : int = r.bar (42)
const z : int = (g (unit))(42)

View File

@ -1,22 +1,15 @@
// Test PascaLIGO arithmetic operators
function mod_op (const n : int) : nat is
begin skip end with n mod 42
function mod_op (const n : int) : nat is n mod 42
function plus_op (const n : int) : int is
begin skip end with n + 42
function plus_op (const n : int) : int is n + 42
function minus_op (const n : int) : int is
begin skip end with n - 42
function minus_op (const n : int) : int is n - 42
function times_op (const n : int) : int is
begin skip end with n * 42
function times_op (const n : int) : int is n * 42
function div_op (const n : int) : int is
begin skip end with n / 2
function div_op (const n : int) : int is n / 2
function int_op (const n : nat) : int is
block { skip } with int(n)
function int_op (const n : nat) : int is int (n)
function neg_op (const n : int) : int is
begin skip end with -n
function neg_op (const n : int) : int is -n

View File

@ -1,4 +1,4 @@
function main (const i : int) : int is
begin
i := i + 1 ;
end with i
block {
i := i + 1
} with i

View File

@ -1,19 +1,19 @@
const x : int = 1; attributes ["inline"]
function foo (const a : int) : int is
begin
block {
const test : int = 2 + a;
attributes ["inline"];
end with test;
} with test;
attributes ["inline"];
const y : int = 1; attributes ["inline"; "other"]
function bar (const b : int) : int is
begin
block {
function test (const z : int) : int is
begin
block {
const r : int = 2 + b + z
end with r;
} with r;
attributes ["inline"; "foo"; "bar"]
end with test(b)
} with test (b)

View File

@ -1,7 +1,9 @@
type storage_ is timestamp
type parameter is unit
type storage is timestamp
type return is list (operation) * storage
function main(const p : unit; const s : storage_) : list(operation) * storage_ is
function main (const p : parameter; const s : storage) : return is
block {
var toto : timestamp := ("badtimestamp" : timestamp);
var stamp : timestamp := ("badtimestamp" : timestamp)
}
with ((nil: list(operation)), toto)
with ((nil: list(operation)), stamp)

View File

@ -1,4 +1,9 @@
type t is (nat * nat)
type s is map(t)
type parameter is unit
function main (const u : unit; const s : s) : (list(operation) * s) is ((nil : list(operation)), s)
type binding is nat * nat
type storage is map (binding)
type return is list (operation) * storage
function main (const param : parameter; const store : storage) : return is
((nil : list (operation)), store)

View File

@ -1,11 +1,12 @@
(**
(*
This test makes sure that the balance is accessible in PascaLIGO.
It's there to detect a regression of: https://gitlab.com/ligolang/ligo/issues/68
It is meant to detect the regression detailled in the following issue: https://gitlab.com/ligolang/ligo/issues/68
*)
type parameter is unit
type storage is tez
type return is list (operation) * storage
function main (const p : unit; const s: tez) : list(operation) * storage is
((nil : list(operation)), balance)
function main (const param : parameter; const store: storage) : return is
((nil : list (operation)), balance)

View File

@ -1,36 +1,35 @@
type storage_ is big_map(int, int) * unit
type foo is big_map(int, int)
type parameter is unit
type storage is big_map (int, int) * unit
type return is list (operation) * storage
function main(const p : unit; const s : storage_) : list(operation) * storage_ is
function main (const p : parameter; const s : storage) : return is
block {
var toto : option (int) := Some(0);
var toto : option (int) := Some (0);
toto := s.0[23];
s.0[2] := 444;
s.0[2] := 444
}
with ((nil: list(operation)), s)
function set_ (var n : int ; var m : foo) : foo is block {
m[23] := n ;
type foo is big_map (int, int)
function set_ (var n : int; var m : foo) : foo is block {
m[23] := n
} with m
function rm (var m : foo) : foo is block {
remove 42 from map m;
remove 42 from map m
} with m
function gf (const m : foo) : int is begin skip end with get_force(23, m)
function gf (const m : foo) : int is get_force (23, m)
function get (const m : foo) : option(int) is begin skip end with m[42]
function get (const m : foo) : option (int) is m[42]
const empty_big_map : big_map(int,int) = big_map end
const empty_big_map : big_map (int,int) = big_map []
const big_map1 : big_map(int,int) = big_map
23 -> 0 ;
42 -> 0 ;
end
const big_map1 : big_map (int,int) = big_map [23 -> 0; 42 -> 0]
function mutimaps (const m : foo ; const n : foo) : foo is block
{
var bar : foo := m ;
bar[42] := 0 ;
n[42] := get_force(42, bar) ;
function mutimaps (const m : foo; const n : foo) : foo is block {
var bar : foo := m;
bar[42] := 0;
n[42] := get_force (42, bar)
} with n

View File

@ -1,16 +1,11 @@
// Test PascaLIGO bitwise operators
function or_op (const n : nat) : nat is
bitwise_or(n , 4n)
function or_op (const n : nat) : nat is bitwise_or (n, 4n)
function and_op (const n : nat) : nat is
bitwise_and(n , 7n)
function and_op (const n : nat) : nat is bitwise_and (n, 7n)
function xor_op (const n : nat) : nat is
bitwise_xor(n , 7n)
function xor_op (const n : nat) : nat is bitwise_xor (n, 7n)
function lsl_op (const n : nat) : nat is
bitwise_lsl(n , 7n)
function lsl_op (const n : nat) : nat is bitwise_lsl (n, 7n)
function lsr_op (const n : nat) : nat is
bitwise_lsr(n , 7n)
function lsr_op (const n : nat) : nat is bitwise_lsr (n, 7n)

View File

@ -1,2 +1 @@
function blockless (const n: int) : int is
n + 10;
function blockless (const n : int) : int is n + 10

View File

@ -1,16 +1,11 @@
// Test PascaLIGO boolean operators
function or_true (const b : bool) : bool is
begin skip end with b or True
function or_true (const b : bool) : bool is b or True
function or_false (const b : bool) : bool is
begin skip end with b or False
function or_false (const b : bool) : bool is b or False
function and_true (const b : bool) : bool is
begin skip end with b and True
function and_true (const b : bool) : bool is b and True
function and_false (const b : bool) : bool is
begin skip end with b and False
function and_false (const b : bool) : bool is b and False
function not_bool (const b: bool) : bool is
begin skip end with not b
function not_bool (const b : bool) : bool is not b

View File

@ -1,8 +1,5 @@
function concat_op (const s : bytes) : bytes is
begin skip end with bytes_concat(s , 0x7070)
function concat_op (const s : bytes) : bytes is bytes_concat (s, 0x7070)
function slice_op (const s : bytes) : bytes is
begin skip end with bytes_slice(1n , 2n , s)
function slice_op (const s : bytes) : bytes is bytes_slice (1n, 2n, s)
function hasherman (const s : bytes) : bytes is
begin skip end with sha_256(s)
function hasherman (const s : bytes) : bytes is sha_256 (s)

View File

@ -1,11 +1,11 @@
function id_string (const p : string) : option(string) is block {
const packed : bytes = bytes_pack(p) ;
} with (bytes_unpack(packed): option(string))
function id_string (const p : string) : option (string) is block {
const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed) : option (string))
function id_int (const p : int) : option(int) is block {
const packed : bytes = bytes_pack(p) ;
} with (bytes_unpack(packed): option(int))
function id_int (const p : int) : option (int) is block {
const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed) : option (int))
function id_address (const p : address) : option(address) is block {
const packed : bytes = bytes_pack(p) ;
} with (bytes_unpack(packed): option(address))
function id_address (const p : address) : option (address) is block {
const packed : bytes = bytes_pack (p)
} with (bytes_unpack (packed) : option (address))

View File

@ -1,5 +1 @@
function chain_id (const tt : chain_id) : chain_id is
block {
var toto : chain_id := get_chain_id ;
} with ( toto )
function chain_id (const tt : chain_id) : chain_id is get_chain_id

View File

@ -1,2 +1,4 @@
function check_signature (const pk: key; const signed: signature; const msg: bytes) : bool is
crypto_check(pk, signed, msg)
function check_signature (const pk : key;
const signed : signature;
const msg: bytes) : bool
is crypto_check (pk, signed, msg)

View File

@ -1,5 +1,4 @@
function foo (const i : int) : int is
block {
function bar (const j : int) : int is
i + j ;
} with bar (i)
function add (const j : int) : int is i+j
} with add (i)

View File

@ -1,6 +1,5 @@
function foobar(const i : int) : int is
function foobar (const i : int) : int is
block {
const j : int = 3 ;
function toto(const k : int) : int is
i + j + k ;
} with toto(42)
const j : int = 3;
function add (const k : int) : int is i+j+k
} with add (42)

View File

@ -1,12 +1,10 @@
// This might seem like it's covered by induction with closure-2.ligo
// But it exists to prevent a regression on the bug patched by:
// This might seem like it is covered by induction with closure-2.ligo,
// but it exists to prevent a regression on the bug patched by:
// https://gitlab.com/ligolang/ligo/commit/faf3bbc06106de98189f1c1673bd57e78351dc7e
function foobar(const i : int) : int is
function foobar (const i : int) : int is
block {
const j : int = 3 ;
const k : int = 4 ;
function toto(const l : int) : int is
i + j + k + l;
} with toto(42)
const j : int = 3;
const k : int = 4;
function add (const l : int) : int is i+j+k+l
} with add (42)

View File

@ -1,7 +1,5 @@
function toto (const i : int) : int is
block {
function tata (const j : int) : int is
i + j ;
function titi (const j : int) : int is
i + j ;
} with tata(i) + titi(i)
function tata (const j : int) : int is i+j;
function titi (const j : int) : int is i+j
} with tata (i) + titi (i)

View File

@ -1,98 +1,113 @@
// Copyright Coase, Inc 2019
type card_pattern_id is nat
type card_pattern is record [
coefficient : tez ;
quantity : nat ;
coefficient : tez;
quantity : nat
]
type card_patterns is map(card_pattern_id , card_pattern)
type card_patterns is map (card_pattern_id, card_pattern)
type card_id is nat
type card is record [
card_owner : address ;
card_pattern : card_pattern_id ;
]
type cards is map(card_id , card)
type storage_type is record [
cards : cards ;
card_patterns : card_patterns ;
next_id : nat ;
type card is record [
card_owner : address;
card_pattern : card_pattern_id
]
type cards is map (card_id, card)
type storage is record [
cards : cards;
card_patterns : card_patterns;
next_id : nat
]
type return is list (operation) * storage
type action_buy_single is record [
card_to_buy : card_pattern_id ;
]
type action_sell_single is record [
card_to_sell : card_id ;
]
type action_transfer_single is record [
card_to_transfer : card_id ;
destination : address ;
card_to_buy : card_pattern_id
]
type action is
| Buy_single of action_buy_single
| Sell_single of action_sell_single
type action_sell_single is record [
card_to_sell : card_id
]
type action_transfer_single is record [
card_to_transfer : card_id;
destination : address
]
type parameter is
Buy_single of action_buy_single
| Sell_single of action_sell_single
| Transfer_single of action_transfer_single
function transfer_single(const action : action_transfer_single ; const s : storage_type) : (list(operation) * storage_type) is
begin
const cards : cards = s.cards ;
const card : card = get_force(action.card_to_transfer , cards) ;
if (card.card_owner =/= source) then failwith ("This card doesn't belong to you") else skip ;
card.card_owner := action.destination ;
cards[action.card_to_transfer] := card ;
s.cards := cards ;
const operations : list(operation) = nil ;
end with (operations , s) ;
function transfer_single (const action : action_transfer_single;
const s : storage) : return is block {
const cards : cards = s.cards;
const card : card = get_force (action.card_to_transfer, cards);
if card.card_owner =/= source then
failwith ("This card doesn't belong to you")
else skip;
card.card_owner := action.destination;
cards[action.card_to_transfer] := card;
s.cards := cards;
const operations : list (operation) = nil
} with (operations, s)
function sell_single(const action : action_sell_single ; const s : storage_type) : (list(operation) * storage_type) is
begin
const card : card = get_force(action.card_to_sell , s.cards) ;
if (card.card_owner =/= source) then failwith ("This card doesn't belong to you") else skip ;
const card_pattern : card_pattern = get_force(card.card_pattern , s.card_patterns) ;
card_pattern.quantity := abs(card_pattern.quantity - 1n);
const card_patterns : card_patterns = s.card_patterns ;
card_patterns[card.card_pattern] := card_pattern ;
s.card_patterns := card_patterns ;
const cards : cards = s.cards ;
remove action.card_to_sell from map cards ;
s.cards := cards ;
const price : tez = card_pattern.coefficient * card_pattern.quantity ;
const receiver : contract(unit) = get_contract(source) ;
const op : operation = transaction(unit , price , receiver) ;
const operations : list(operation) = list op end ;
end with (operations , s)
function sell_single (const action : action_sell_single;
const s : storage) : return is
block {
const card : card = get_force (action.card_to_sell, s.cards);
if card.card_owner =/= source
then failwith ("This card doesn't belong to you")
else skip;
const card_pattern : card_pattern =
get_force (card.card_pattern, s.card_patterns);
card_pattern.quantity := abs (card_pattern.quantity - 1n);
const card_patterns : card_patterns = s.card_patterns;
card_patterns[card.card_pattern] := card_pattern;
s.card_patterns := card_patterns;
const cards : cards = s.cards;
remove action.card_to_sell from map cards;
s.cards := cards;
const price : tez = card_pattern.coefficient * card_pattern.quantity;
const receiver : contract (unit) = get_contract (source);
const op : operation = transaction (unit, price, receiver);
const operations : list (operation) = list [op]
} with (operations, s)
function buy_single(const action : action_buy_single ; const s : storage_type) : (list(operation) * storage_type) is
begin
function buy_single (const action : action_buy_single;
const s : storage) : return is
block {
// Check funds
const card_pattern : card_pattern = get_force(action.card_to_buy , s.card_patterns) ;
const price : tez = card_pattern.coefficient * (card_pattern.quantity + 1n) ;
if (price > amount) then failwith ("Not enough money") else skip ;
const card_pattern : card_pattern =
get_force (action.card_to_buy, s.card_patterns);
const price : tez =
card_pattern.coefficient * (card_pattern.quantity + 1n);
if price > amount then failwith ("Not enough money") else skip;
// Administrative procedure
const operations : list(operation) = nil ;
const operations : list(operation) = nil;
// Increase quantity
card_pattern.quantity := card_pattern.quantity + 1n ;
const card_patterns : card_patterns = s.card_patterns ;
card_patterns[action.card_to_buy] := card_pattern ;
s.card_patterns := card_patterns ;
card_pattern.quantity := card_pattern.quantity + 1n;
const card_patterns : card_patterns = s.card_patterns;
card_patterns[action.card_to_buy] := card_pattern;
s.card_patterns := card_patterns;
// Add card
const cards : cards = s.cards ;
cards[s.next_id] := record
card_owner = source ;
card_pattern = action.card_to_buy ;
end ;
s.cards := cards ;
s.next_id := s.next_id + 1n ;
end with (operations , s)
const cards : cards = s.cards;
cards[s.next_id] := record [
card_owner = source;
card_pattern = action.card_to_buy
];
s.cards := cards;
s.next_id := s.next_id + 1n
} with (operations, s)
function main(const action : action ; const s : storage_type) : (list(operation) * storage_type) is
block {skip} with
function main (const action : parameter; const s : storage) : return is
case action of
| Buy_single (bs) -> buy_single (bs , s)
| Sell_single (as) -> sell_single (as , s)
| Transfer_single (at) -> transfer_single (at , s)
Buy_single (bs) -> buy_single (bs, s)
| Sell_single (as) -> sell_single (as, s)
| Transfer_single (at) -> transfer_single (at, s)
end

View File

@ -1,10 +1 @@
// Test if conditional with trivial conditions in PascaLIGO
function main (const i : int) : int is
begin
if 1 = 1 then
i := 42
else
i := 0
end with i
function main (const i : int) : int is if 1 = 1 then 42 else 0

View File

@ -1,16 +1,10 @@
// Test if conditional in PascaLIGO
function main (const i : int) : int is
begin
var result : int := 23 ;
if i = 2 then
result := 42
else
result := 0
end with result
block {
var result : int := 23;
if i = 2 then result := 42 else result := 0
} with result
function foo (const b : bool) : int is
begin
var x : int := 41 ;
x := 1 + (if b then x else main(x)) ;
end with x
block {
const x : int = 41
} with 1 + (if b then x else main (x))

View File

@ -1,6 +1,7 @@
type some_type is int
type t is int
function main (const p : int ; const s : some_type) : (list(operation) * int) is
block { skip } // skip is a do nothing instruction, needed for empty blocks
function main (const p : int ; const s : t) : list (operation) * int is
block {
skip
} // skip is a do nothing instruction, needed for empty blocks
with ((nil : list(operation)), p + s)

View File

@ -1,3 +1,3 @@
function hasherman512 (const s: bytes) : bytes is sha_512(s)
function hasherman512 (const s: bytes) : bytes is sha_512 (s)
function hasherman_blake (const s: bytes) : bytes is blake2b(s)
function hasherman_blake (const s: bytes) : bytes is blake2b (s)

View File

@ -1,5 +1,5 @@
// Test PasaLIGO variable declarations inside of a block
function main (const i : int) : int is block {
const j : int = 42 ;
const j : int = 42
} with j

View File

@ -1,8 +1,5 @@
// Test PascaLIGO top level declarations
// Test PascaLIGO top-level declarations
const foo : int = 42
function main (const i : int) : int is
begin
skip
end with i + foo
function main (const i : int) : int is i + foo

View File

@ -1,31 +1,29 @@
//Test deep_access in PascalLigo
type pii is (int*int)
type ppi is record x:pii; y:pii end
type ppp is (ppi*ppi)
// Test deep access
function main (const toto : unit) : int is block {
var a : ppp := (
record
x = (0,1);
y = (10,11);
end ,
record
x = (100,101);
y = (110,111);
end
) ;
a.0.x.0 := 2;
const b:int = a.0.x.0;
} with b
type pii is int * int
type ppi is record [x : pii; y : pii]
type ppp is ppi * ppi
function main (const toto : unit) : int is
block {
var a : ppp :=
(record [x = (0,1); y = (10,11)],
record [x = (100,101); y = (110,111)]);
a.0.x.0 := 2;
} with a.0.x.0
function asymetric_tuple_access(const foo : unit) : int is block {
var mytuple : int * (int * (int * int)) := (0,(1,(2,3))) ;
} with mytuple.0 + mytuple.1.0 + mytuple.1.1.0 + mytuple.1.1.1
function asymetric_tuple_access (const foo : unit) : int is
block {
var tuple : int * (int * (int * int)) := (0,(1,(2,3)))
} with tuple.0 + tuple.1.0 + tuple.1.1.0 + tuple.1.1.1
type nested_record_t is record
nesty : (record mymap : map(int,string) ; end) ;
end
function nested_record (var nee : nested_record_t) : string is block {
nee.nesty.mymap[1] := "one" ;
} with ( get_force(1, nee.nesty.mymap) )
type nested_record_t is
record [nesty : record [mymap : map (int,string)]]
function nested_record (var nee : nested_record_t) : string is
block {
nee.nesty.mymap[1] := "one"
} with get_force (1, nee.nesty.mymap)

View File

@ -1,16 +1,19 @@
type action is
| Increment of int
type parameter is
Increment of int
| Decrement of int
function increment(const i : int ; const n : int) : int is
block { skip } with (i + n)
type storage is int
function decrement(const i : int ; const n : int) : int is
block { skip } with (i - n)
type return is list (operation) * storage
function main (const p : action ; const s : int) : (list(operation) * int) is
block {skip} with ((nil : list(operation)),
case p of
| Increment (n) -> increment (s, n)
| Decrement (n) -> decrement (s, n)
end)
function increment (const i : int; const n : int) : int is i+n
function decrement (const i : int; const n : int) : int is i-n
const nop : list (operation) = nil
function main (const action : parameter; const store : storage) : return is
case action of
Increment (n) -> (nop, increment (store, n))
| Decrement (n) -> (nop, decrement (store, n))
end

View File

@ -1,8 +1,11 @@
function main(const p : unit; const s : int) : list(operation) * int is
((list end : list(operation)), s + 1)
type parameter is unit
type storage is int
type return is list (operation) * storage
function main(const p : unit; const s : int) : list(operation) * int is
begin
const ret : list(operation) * int = main(p, s)
end
with (ret.0, ret.1 + 1)
function main(const p : parameter; const s : storage) : return is
((nil : list(operation)), s+1)
function main (const p : parameter; const s : storage) : return is
block {
const ret : return = main (p, s)
} with (ret.0, ret.1 + 1)

View File

@ -1,9 +1,9 @@
type foo is
| Bar of int
| Baz
type t is
Bar of int
| Baz
function main (const f: foo) : int is
(case f of
| Bar (n) -> n
| Baz -> -1
end)
function main (const x : t) : int is
case x of
Bar (n) -> n
| Baz -> -1
end

View File

@ -1,16 +1,19 @@
function cb(const a : address; const s : unit) : list(operation) * unit is
type storage is unit
type return is list (operation) * storage
function cb (const a : address; const s : storage) : return is
block {
const c : contract(unit) = get_entrypoint("%cb", a)
const c : contract (unit) = get_entrypoint ("%cb", a)
}
with (list transaction(unit, 0mutez, c) end, s)
with (list [transaction (unit, 0mutez, c)], s)
function cbo(const a : address; const s : unit) : list(operation) * unit is
function cbo (const a : address; const s : storage) : return is
block {
const c : contract(unit) =
case (get_entrypoint_opt("%cbo", a) : option(contract (unit))) of
| Some (c) -> c
| None -> (failwith ("entrypoint not found") : contract (unit))
const c : contract (unit) =
case (get_entrypoint_opt ("%cbo", a) : option (contract (unit))) of
Some (c) -> c
| None -> (failwith ("entrypoint not found") : contract (unit))
end
}
with (list transaction(unit, 0mutez, c) end, s)
} with (list [transaction(unit, 0mutez, c)], s)

View File

@ -1,11 +1,5 @@
type myrec is record
foo : nat;
bar : string;
end;
type t is record [foo : nat; bar : string]
const a : myrec = record
foo = 0n;
bar = "bar";
end;
const a : t = record [foo = 0n; bar = "bar"]
const b : int = 2 ;
const b : int = 2

View File

@ -1,37 +1,43 @@
type param is
| Zero of nat
| Pos of nat
type parameter is
Zero of nat
| Pos of nat
function main (const p : param; const s : unit) : list(operation) * unit is
type storage is unit
type return is list (operation) * storage
function main (const p : parameter; const s : storage) : return is
block {
case p of
| Zero (n) -> if n > 0n then failwith("fail") else skip
| Pos (n) -> if n > 0n then skip else failwith("fail")
Zero (n) -> if n > 0n then failwith ("fail") else skip
| Pos (n) -> if n > 0n then skip else failwith ("fail")
end
}
with ((nil : list(operation)), s)
with ((nil : list (operation)), s)
function foobar (const i : int) : int is
block {
var p : param := Zero (42n) ;
if i > 0 then block {
i := i + 1 ;
if i > 10 then block {
i := 20 ;
failwith ("who knows") ;
i := 30 ;
} else skip
} else block {
case p of
| Zero (n) -> failwith ("wooo")
| Pos (n) -> skip
end
var p : parameter := Zero (42n);
if i > 0 then {
i := i + 1;
if i > 10 then {
i := 20;
failwith ("who knows");
i := 30 // Should be no-op
}
else skip
}
} with case p of
| Zero (n) -> i
| Pos (n) -> (failwith ("waaaa") : int)
end
else
case p of
Zero (n) -> failwith ("wooo")
| Pos (n) -> skip
end
} with
case p of
Zero (n) -> i
| Pos (n) -> (failwith ("waaaa") : int)
end
function failer(const p : int) : int is block {
if p = 1 then failwith("some_string") else skip ;
function failer (const p : int) : int is block {
if p = 1 then failwith ("some_string") else skip
} with p

View File

@ -1,11 +1,2 @@
// This was meant to test the for loop in PascaLIGO
// But for whatever reason, the LIGO compiler currently thinks this is a 'complex loop'
// even though it isn't.
// See this error:
// $ ligo dry-run for.ligo main 0 0
// bounded iterators: only simple for loops are supported yet
// {"loop_loc":"in file \"for.ligo\", line 4, characters 10-42"}
function main (const a: int) : int is
block { for i := 0 to 100 block { skip } } with i;
block { for i := 0 to 100 block { skip } } with i

View File

@ -1,9 +1,9 @@
// Test a PascaLIGO function with more complex logic than function.ligo
function main (const i : int) : int is
begin
var j : int := 0 ;
var k : int := 1 ;
j := k + i ;
k := i + j ;
end with (k + j)
block {
var j : int := 0;
var k : int := 1;
j := k + i;
k := i + j
} with k + j

View File

@ -1,10 +1,7 @@
// Test a PascaLIGO function which uses other functions as subroutines
function inc ( const i : int ) : int is
block { skip } with i + 1
function inc (const i : int) : int is i+1
function double_inc ( const i : int ) : int is
block { skip } with inc(i + 1)
function double_inc (const i : int) : int is inc (i+1)
function foo ( const i : int ) : int is
block { skip } with inc(i) + double_inc(i)
function foo (const i : int) : int is inc (i) + double_inc (i)

View File

@ -1,6 +1,3 @@
// Test a trivial PascaLIGO function
function main (const i : int) : int is
begin
skip
end with i
function main (const i : int) : int is i

View File

@ -1,16 +1,19 @@
function cb(const s : unit) : list(operation) * unit is
type storage is unit
type return is list (operation) * storage
function cb (const s : storage) : return is
block {
const c : contract(unit) = get_contract(source)
const c : contract (unit) = get_contract (source)
}
with (list transaction(unit, 0mutez, c) end, s)
with (list [transaction(unit, 0mutez, c)], s)
function cbo(const s : unit) : list(operation) * unit is
function cbo (const s : unit) : return is
block {
const c : contract(unit) =
case (get_contract_opt(source) : option(contract (unit))) of
| Some (c) -> c
| None -> (failwith ("contract not found") : contract (unit))
const c : contract (unit) =
case (get_contract_opt (source) : option (contract (unit))) of
Some (c) -> c
| None -> (failwith ("contract not found") : contract (unit))
end
}
with (list transaction(unit, 0mutez, c) end, s)
with (list [transaction(unit, 0mutez, c)], s)

View File

@ -1,6 +1,6 @@
type heap_element is int * string
type heap_elt is int * string
function heap_element_lt(const x : heap_element ; const y : heap_element) : bool is
block { skip } with x.0 < y.0
function heap_elt_lt (const x : heap_elt;
const y : heap_elt) : bool is x.0 < y.0
#include "heap.ligo"

View File

@ -1,93 +1,95 @@
// Implementation of the heap data structure in PascaLIGO
// See: https://en.wikipedia.org/wiki/Heap_%28data_structure%29
type heap is map(nat, heap_element) ;
type heap is map (nat, heap_elt)
function is_empty (const h : heap) : bool is
block {skip} with size(h) = 0n
function is_empty (const h : heap) : bool is size (h) = 0n
function get_top (const h : heap) : heap_element is
block {skip} with get_force(1n, h)
function get_top (const h : heap) : heap_elt is get_force (1n, h)
function pop_switch (const h : heap) : heap is
block {
const result : heap_element = get_top (h) ;
const s : nat = size(h) ;
const last : heap_element = get_force(s, h) ;
remove 1n from map h ;
h[1n] := last ;
const result : heap_elt = get_top (h);
const s : nat = size (h);
const last : heap_elt = get_force (s, h);
remove 1n from map h;
h[1n] := last
} with h
function pop_ (const h : heap) : nat is
begin
const result : heap_element = get_top (h) ;
const s : nat = size(h) ;
var current : heap_element := get_force(s, h) ;
const i : nat = 1n ;
const left : nat = 2n * i ;
const right : nat = left + 1n ;
remove 1n from map h ;
h[1n] := current ;
var largest : nat := i ;
if (left <= s and heap_element_lt(get_force(s , h) , get_force(left , h))) then
largest := left
else if (right <= s and heap_element_lt(get_force(s , h) , get_force(right , h))) then
largest := right
else skip
end with largest
block {
const result : heap_elt = get_top (h);
const s : nat = size (h);
var current : heap_elt := get_force (s, h);
const i : nat = 1n;
const left : nat = 2n * i;
const right : nat = left + 1n;
remove 1n from map h;
h[1n] := current;
var largest : nat := i;
const tmp : heap_elt = get_force (s, h);
if left <= s and heap_elt_lt (tmp, get_force (left,h))
then largest := left
else
if right <= s and heap_elt_lt (tmp, get_force (right,h))
then largest := right
else skip
} with largest
function insert (const h : heap ; const e : heap_element) : heap is
begin
var i : nat := size(h) + 1n ;
h[i] := e ;
var largest : nat := i ;
var parent : nat := 0n ;
while (largest =/= i) block {
parent := i / 2n ;
largest := i ;
if (parent >= 1n) then block {
if (heap_element_lt(get_force(parent , h) , get_force(i , h))) then block {
largest := parent ;
const tmp : heap_element = get_force(i , h) ;
h[i] := get_force(parent , h) ;
h[parent] := tmp ;
function insert (const h : heap ; const e : heap_elt) : heap is
block {
var i : nat := size (h) + 1n;
h[i] := e;
var largest : nat := i;
var parent : nat := 0n;
while largest =/= i block {
parent := i/2n;
largest := i;
if parent >= 1n then {
if heap_elt_lt (get_force (parent,h), get_force(i,h))) then {
largest := parent;
const tmp : heap_elt = get_force (i,h);
h[i] := get_force(parent, h);
h[parent] := tmp
} else skip
} else skip
}
end with h
} with h
function pop (const h : heap) : (heap * heap_element * nat) is
begin
const result : heap_element = get_top (h) ;
var s : nat := size(h) ;
const last : heap_element = get_force(s, h) ;
remove s from map h ;
h[1n] := last ;
s := size(h) ;
var i : nat := 0n ;
var largest : nat := 1n ;
var left : nat := 0n ;
var right : nat := 0n ;
var c : nat := 0n ;
while (largest =/= i) block {
c := c + 1n ;
i := largest ;
left := 2n * i ;
right := left + 1n ;
if (left <= s) then begin
if (heap_element_lt(get_force(left , h) , get_force(i , h))) then begin
largest := left ;
const tmp : heap_element = get_force(i , h) ;
h[i] := get_force(left , h) ;
h[left] := tmp ;
end else skip ;
end else if (right <= s) then begin
if (heap_element_lt(get_force(right , h) , get_force(i , h))) then begin
largest := right ;
const tmp : heap_element = get_force(i , h) ;
h[i] := get_force(right , h) ;
h[left] := tmp ;
end else skip ;
end else skip ;
}
end with (h , result , c)
function pop (const h : heap) : heap * heap_elt * nat is
block {
const result : heap_elt = get_top (h);
var s : nat := size (h);
const last : heap_elt = get_force (s,h);
remove s from map h;
h[1n] := last;
s := size (h);
var i : nat := 0n;
var largest : nat := 1n;
var left : nat := 0n;
var right : nat := 0n;
var c : nat := 0n;
while largest =/= i block {
c := c + 1n;
i := largest;
left := 2n * i;
right := left + 1n;
if left <= s then {
if heap_elt_lt (get_force (left,h), get_force(i,h)) then {
largest := left;
const tmp : heap_elt = get_force(i,h);
h[i] := get_force (left, h);
h[left] := tmp
} else skip
}
else
if right <= s then {
if heap_elt_lt (get_force (right, h), get_force (i,h)) then {
largest := right;
const tmp : heap_elt = get_force (i,h);
h[i] := get_force (right, h);
h[left] := tmp
} else skip
} else skip
}
} with (h, result, c)

View File

@ -1,27 +1,27 @@
// Test a PascaLIGO function which takes another PascaLIGO function as an argument
(* Test a PascaLIGO function which takes another function as an
argument *)
function foobar (const i : int) : int is
begin
block {
function foo (const i : int) : int is i;
function bar (const f : int -> int) : int is f (i);
end with bar (foo);
} with bar (foo)
// higher order function with more than one argument
function higher2(const i : int; const f : int -> int): int is
begin
const ii: int = f (i)
end with ii
function higher2 (const i : int; const f : int -> int): int is f (i)
function foobar2 (const i : int) : int is
begin
block {
function foo2 (const i : int) : int is i
end with higher2 (i,foo2)
} with higher2 (i, foo2)
const a : int = 0;
const a : int = 0
function foobar3 (const i : int) : int is
begin
block {
function foo2 (const i : int) : int is a+i
end with higher2 (i,foo2)
} with higher2 (i, foo2)
function f (const i : int) : int is i
@ -29,17 +29,15 @@ function g (const i : int) : int is f (i)
function foobar4 (const i : int) : int is g (g (i))
function higher3(const i : int; const f : int -> int; const g : int -> int)
: int is
begin
const ii : int = f(g(i))
end with ii
function higher3 (const i : int;
const f : int -> int;
const g : int -> int) : int is f (g (i))
function foobar5 (const i : int) : int is
begin
block {
const a : int = 0;
function foo (const i : int) : int is a+i;
function goo (const i : int) : int is foo (i)
end with higher3(i,foo,goo)
} with higher3 (i, foo, goo)
function foobar6 (const i : int) : int -> int is f

View File

@ -1 +1 @@
function main (const kh: key_hash) : contract(unit) is implicit_account(kh)
function main (const kh: key_hash) : contract (unit) is implicit_account (kh)

View File

@ -1,2 +1 @@
function main (const i: int) : option(nat) is
block {skip} with is_nat(i)
function main (const i : int) : option (nat) is is_nat (i)

View File

@ -1,5 +1,7 @@
function check_hash_key (const kh1 : key_hash; const k2 : key) : bool*key_hash is block {
var ret : bool := False ;
var kh2 : key_hash := crypto_hash_key(k2) ;
if kh1 = kh2 then ret := True else skip;
} with (ret, kh2)
function check_hash_key (const kh1 : key_hash;
const k2 : key) : bool * key_hash is
block {
var ret : bool := False;
var kh2 : key_hash := crypto_hash_key (k2);
if kh1 = kh2 then ret := True else skip
} with (ret, kh2)

View File

@ -1,7 +1,3 @@
function f (const x : unit) : unit is
begin skip end with unit
function f (const x : unit) : unit is Unit
function main (const p : unit ; const s : unit) : unit is
begin
var y : unit := f(unit) ;
end with y
function main (const p : unit ; const s : unit) : unit is f (Unit)

View File

@ -1,49 +1,33 @@
// Test list type and related built-in functions in PascaLIGO
type foobar is list(int)
type foobar is list (int)
const fb : foobar = list
23 ;
42 ;
end
const fb : foobar = list [23; 42]
const fb2 : foobar = 144 # fb
const fb3 : foobar = cons(688 , fb2)
const fb3 : foobar = cons (688, fb2)
function size_ (const m : foobar) : nat is
block {skip} with (size(m))
function size_ (const m : foobar) : nat is size (m)
// function hdf (const m : foobar) : int is begin skip end with hd(m)
// function hdf (const m : foobar) : int is hd (m)
const bl : foobar = list
144 ;
51 ;
42 ;
120 ;
421 ;
end
const bl : foobar = list [144; 51; 42; 120; 421]
function fold_op (const s: list(int)) : int is
begin
function aggregate (const prec: int; const cur: int) : int is
begin
skip
end with prec + cur
end with list_fold(aggregate, s, 10)
function iter_op (const s : list(int)) : int is
begin
var r : int := 0 ;
function aggregate (const i : int) : unit is
begin
r := r + i ;
end with unit ;
list_iter(aggregate, s) ;
end with r
function map_op (const s : list(int)) : list(int) is
function fold_op (const s : list (int)) : int is
block {
function increment (const i : int) : int is block { skip } with i + 1
} with list_map(increment, s)
function aggregate (const prec: int; const cur: int) : int is prec+cur
} with list_fold (aggregate, s, 10)
function iter_op (const s : list (int)) : int is
block {
var r : int := 0;
function aggregate (const i : int) : unit is
block { r := r + i } with unit;
list_iter (aggregate, s)
} with r
function map_op (const s : list (int)) : list (int) is
block {
function increment (const i : int) : int is i+1
} with list_map (increment, s)

View File

@ -1,193 +1,188 @@
// Test while loops in PascaLIGO
function counter (var n : nat) : nat is block {
var i : nat := 0n ;
while i < n block {
i := i + 1n;
}
} with i
function counter (var n : nat) : nat is
block {
var i : nat := 0n;
while i < n block {
i := i + 1n
}
} with i
function while_sum (var n : nat) : nat is block {
var i : nat := 0n ;
var r : nat := 0n ;
while i < n block {
i := i + 1n;
r := r + i;
}
} with r
function while_sum (var n : nat) : nat is
block {
var i : nat := 0n;
var r : nat := 0n;
while i < n block {
i := i + 1n;
r := r + i
}
} with r
function for_sum (var n : nat) : int is block {
var acc : int := 0 ;
for i := 1 to int(n)
begin
acc := acc + i;
end
} with acc
function for_sum (var n : nat) : int is
block {
var acc : int := 0;
for i := 1 to int (n)
block {
acc := acc + i
}
} with acc
function for_collection_list (var nee : unit) : (int * string) is block {
var acc : int := 0;
var st : string := "to";
var mylist : list(int) := list 1; 1; 1 end;
for x in list mylist
begin
function for_collection_list (var nee : unit) : (int * string) is
block {
var acc : int := 0;
var st : string := "to";
var mylist : list (int) := list [1; 1; 1];
for x in list mylist
block {
acc := acc + x;
st := st ^ "to"
}
} with (acc, st)
function for_collection_set (var nee : unit) : int * string is
block {
var acc : int := 0;
var st : string := "to";
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
acc := acc + x;
st := st ^ "to";
end
} with (acc, st)
st := st ^ "to"
}
} with (acc, st)
function for_collection_set (var nee : unit) : (int * string) is block {
var acc : int := 0;
var st : string := "to";
var myset : set(int) := set 1; 2; 3 end;
for x in set myset
begin
acc := acc + x ;
st := st^"to" ;
end
} with (acc, st)
function for_collection_if_and_local_var (var nee : unit) : int is
block {
var acc : int := 0;
const theone : int = 1;
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
const thetwo : int = 2;
if x = theone then acc := acc + x
else if x = thetwo then acc := acc + thetwo
else acc := acc + 10
}
} with acc
function for_collection_if_and_local_var (var nee : unit) : int is block {
var acc : int := 0 ;
const theone : int = 1 ;
var myset : set(int) := set 1 ; 2 ; 3 end ;
for x in set myset
begin
const thetwo : int = 2 ;
if x=theone then
acc := acc + x
else if x=thetwo then
acc := acc + thetwo;
else
acc := acc + 10;
end
} with acc
function for_collection_rhs_capture (var nee : unit) : int is
block {
var acc : int := 0;
const mybigint : int = 1000;
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
if x = 1 then acc := acc + mybigint
else acc := acc + 10
}
} with acc
function for_collection_rhs_capture (var nee : unit) : int is block {
var acc : int := 0 ;
const mybigint : int = 1000 ;
var myset : set(int) := set 1 ; 2 ; 3 end ;
for x in set myset
begin
if x=1 then acc := acc + mybigint;
else acc := acc + 10;
end
} with acc
function for_collection_proc_call (var nee : unit) : int is
block {
var acc : int := 0;
var myset : set (int) := set [1; 2; 3];
for x in set myset block {
if x = 1 then
acc := acc + for_collection_rhs_capture (unit)
else acc := acc + 10
}
} with acc
function for_collection_proc_call (var nee : unit) : int is block {
var acc : int := 0 ;
var myset : set(int) := set 1 ; 2 ; 3 end ;
for x in set myset
begin
if x=1 then
acc := acc + for_collection_rhs_capture(unit);
else
acc := acc + 10;
end
} with acc
function for_collection_comp_with_acc (var nee : unit) : int is block {
var myint : int := 0 ;
var mylist : list(int) := list 1 ; 10 ; 15 end;
for x in list mylist
begin
function for_collection_comp_with_acc (var nee : unit) : int is
block {
var myint : int := 0;
var mylist : list (int) := list [1; 10; 15];
for x in list mylist block {
if x < myint then skip;
else myint := myint + 10
end
} with myint
}
} with myint
function for_collection_with_patches (var nee : unit) : map(string,int) is block {
var myint : int := 12 ;
var mylist : list(string) := list "I"; "am"; "foo" end;
var mymap : map(string,int) := map end;
for x in list mylist
begin
patch mymap with map [x -> myint];
end
} with mymap
function for_collection_with_patches (var nee : unit) : map (string,int) is
block {
var myint : int := 12;
var mylist : list (string) := list ["I"; "am"; "foo"];
var mymap : map (string,int) := map [];
for x in list mylist block {
patch mymap with map [x -> myint]
}
} with mymap
function for_collection_empty (var nee : unit) : int is block {
var acc : int := 0 ;
var myset : set(int) := set 1; 2; 3 end;
for x in set myset
begin
function for_collection_empty (var nee : unit) : int is
block {
var acc : int := 0;
var myset : set(int) := set [1; 2; 3];
for x in set myset block {
skip
end
} with acc
}
} with acc
function for_collection_map_kv (var nee : unit) : (int * string) is block {
var acc : int := 0;
var st : string := "";
var mymap : map(string,int) := map "1" -> 1; "2" -> 2; "3" -> 3 end;
for k -> v in map mymap
begin
function for_collection_map_kv (var nee : unit) : int * string is
block {
var acc : int := 0;
var st : string := "";
var mymap : map (string, int) := map ["1" -> 1; "2" -> 2; "3" -> 3];
for k -> v in map mymap block {
acc := acc + v;
st := st ^ k;
end
} with (acc, st)
}
} with (acc, st)
function for_collection_map_k (var nee : unit) : string is block {
var st : string := "" ;
var mymap : map(string,int) := map "1" -> 1 ; "2" -> 2 ; "3" -> 3 end ;
for k in map mymap
begin
st := st ^ k;
end
} with st
function for_collection_map_k (var nee : unit) : string is
block {
var st : string := "";
var mymap : map (string, int) := map ["1" -> 1; "2" -> 2; "3" -> 3];
for k in map mymap block {
st := st ^ k
}
} with st
function nested_for_collection (var nee : unit) : (int*string) is block {
var myint : int := 0;
var mystoo : string := "";
var mylist : list(int) := list 1 ; 2 ; 3 end ;
var mymap : map(string,string) := map " one" -> "," ; "two" -> " " end ;
function nested_for_collection (var nee : unit) : int * string is
block {
var myint : int := 0;
var mystoo : string := "";
var mylist : list(int) := list [1; 2; 3];
var mymap : map (string, string) := map [" one" -> ","; "two" -> " "];
for i in list mylist block {
myint := myint + i;
var myset : set (string) := set ["1"; "2"; "3"];
for st in set myset block {
myint := myint + i;
mystoo := mystoo ^ st;
for k -> v in map mymap block {
mystoo := mystoo ^ k ^ v
}
}
}
} with (myint, mystoo)
for i in list mylist
begin
myint := myint + i ;
var myset : set(string) := set "1" ; "2" ; "3" end ;
for st in set myset
begin
myint := myint + i ;
mystoo := mystoo ^ st ;
for k -> v in map mymap
begin
mystoo := mystoo ^ k ^ v ;
end
end
end
} with (myint,mystoo)
function nested_for_collection_local_var (var nee : unit) : (int*string) is block {
var myint : int := 0;
var myst : string := "";
var mylist : list(int) := list 1 ; 2 ; 3 end ;
for i in list mylist
begin
var myst_loc : string := "" ;
myint := myint + i ;
var myset : set(string) := set "1" ; "2" ; "3" end ;
for st in set myset
begin
myint := myint + i ;
myst_loc := myst_loc ^ st ;
end;
myst := myst_loc ^ myst ;
end
} with (myint,myst)
function nested_for_collection_local_var (var nee : unit) : int*string is
block {
var myint : int := 0;
var myst : string := "";
var mylist : list (int) := list [1; 2; 3];
for i in list mylist block {
var myst_loc : string := "";
myint := myint + i;
var myset : set (string) := set ["1"; "2"; "3"];
for st in set myset block {
myint := myint + i;
myst_loc := myst_loc ^ st;
};
myst := myst_loc ^ myst
}
} with (myint, myst)
function dummy (const n : nat) : nat is block {
while False block { skip }
} with n
function inner_capture_in_conditional_block (var nee : unit) : bool*int is block {
var count : int := 1 ;
var ret : bool := False ;
var mylist : list(int) := list 1 ; 2 ; 3 end ;
for it1 in list mylist block {
for it2 in list mylist block {
if count = it2 then ret := not (ret)
else skip;
};
count := count + 1;
}
} with (ret,count)
function inner_capture_in_conditional_block (var nee : unit) : bool * int is
block {
var count : int := 1;
var ret : bool := False;
var mylist : list (int) := list [1; 2; 3];
for it1 in list mylist block {
for it2 in list mylist block {
if count = it2 then ret := not (ret) else skip
};
count := count + 1
}
} with (ret, count)

View File

@ -1,23 +1,20 @@
// Test map type and related built-in functions in PascaLIGO
type foobar is map(int, int)
type foobar is map (int, int)
const empty_map : foobar = map end
const empty_map : foobar = map []
const map1 : foobar = map
144 -> 23 ;
51 -> 23 ;
42 -> 23 ;
120 -> 23 ;
421 -> 23 ;
end
const map2 : foobar = map
23 -> 0 ;
42 -> 0 ;
end
const map1 : foobar = map [
144 -> 23;
51 -> 23;
42 -> 23;
120 -> 23;
421 -> 23]
function set_ (var n : int ; var m : foobar) : foobar is block {
m[23] := n ;
const map2 : foobar = map [23 -> 0; 42 -> 0]
function set_ (var n : int; var m : foobar) : foobar is block {
m[23] := n
} with m
@ -25,50 +22,43 @@ function rm (var m : foobar) : foobar is block {
remove 42 from map m
} with m
function patch_ (var m: foobar) : foobar is block {
function patch_ (var m : foobar) : foobar is block {
patch m with map [0 -> 5; 1 -> 6; 2 -> 7]
} with m
function patch_deep (var m: foobar * nat) : foobar * nat is
begin patch m.0 with map [1 -> 9]; end with m
function patch_deep (var m : foobar * nat) : foobar * nat is
block { patch m.0 with map [1 -> 9] } with m
function size_ (const m : foobar) : nat is
block {skip} with (size(m))
function size_ (const m : foobar) : nat is size (m)
function gf (const m : foobar) : int is begin skip end with get_force(23, m)
function gf (const m : foobar) : int is get_force (23, m)
function get (const m : foobar) : option(int) is
begin
skip
end with m[42]
function get (const m : foobar) : option (int) is m[42]
function get_ (const m : foobar) : option(int) is
begin
skip
end with map_get(42 , m)
function get_ (const m : foobar) : option (int) is map_get (42, m)
function mem (const k: int; const m: foobar) : bool is map_mem(k, m)
function mem (const k: int; const m: foobar) : bool is map_mem (k, m)
function iter_op (const m : foobar) : unit is
block {
function aggregate (const i : int ; const j : int) : unit is block
{ if (i=j) then skip else failwith("fail") } with unit ;
// map_iter(m , aggregate) ;
} with map_iter(aggregate, m) ;
function aggregate (const i : int; const j : int) : unit is block
{ if i=j then skip else failwith ("fail") } with unit
} with map_iter (aggregate, m)
function map_op (const m : foobar) : foobar is
block {
function increment (const i : int ; const j : int) : int is block { skip } with j + 1 ;
} with map_map(increment, m) ;
function increment (const i : int; const j : int) : int is j+1
} with map_map (increment, m)
function fold_op (const m : foobar) : int is
block {
function aggregate (const i : int ; const j : (int * int)) : int is block { skip } with i + j.0 + j.1 ;
} with map_fold(aggregate, m , 10)
function aggregate (const i : int; const j : int * int) : int is
i + j.0 + j.1
} with map_fold(aggregate, m, 10)
function deep_op (var m : foobar) : foobar is
block {
var coco : (int*foobar) := (0, m);
remove 42 from map coco.1 ;
coco.1[32] := 16 ;
var coco : int * foobar := (0, m);
remove 42 from map coco.1;
coco.1[32] := 16
} with coco.1

View File

@ -1,37 +1,37 @@
// Test the pattern matching functionality of PascaLIGO
function match_bool (const i : int) : int is
begin
var result : int := 23 ;
block {
var result : int := 23;
case i = 2 of
| True -> result := 42
True -> result := 42
| False -> result := 0
end
end with result
} with result
function match_option (const o : option(int)) : int is
begin
var result : int := 23 ;
function match_option (const o : option (int)) : int is
block {
var result : int := 23;
case o of
| None -> skip
None -> skip
| Some (s) -> result := s
end
end with result
} with result
function match_expr_bool (const i : int) : int is
case i = 2 of
| True -> 42
True -> 42
| False -> 0
end
function match_expr_option (const o : option(int)) : int is
function match_expr_option (const o : option (int)) : int is
case o of
| None -> 42
None -> 42
| Some (s) -> s
end
function match_expr_list (const l : list(int)) : int is
function match_expr_list (const l : list (int)) : int is
case l of
| nil -> -1
nil -> -1
| hd # tl -> hd
end

View File

@ -1,10 +1,14 @@
// Test functions with several parameters in PascaLIGO
function ab(const a : int; const b : int) : int is
begin skip end with (a + b)
function ab (const a : int; const b : int) : int is a+b
function abcd(const a : int; const b : int; const c : int; const d : int) : int is
begin skip end with (a + b + c + d + 2)
function abcd (const a : int;
const b : int;
const c : int;
const d : int) : int is a+b+c+d+2
function abcde(const a : int; const b : int; const c : int; const d : int; const e : int) : int is
begin skip end with (c + e + 3)
function abcde (const a : int;
const b : int;
const c : int;
const d : int;
const e : int) : int is c+e+3

View File

@ -1,118 +1,150 @@
// storage type
type threshold_t is nat
type max_proposal_t is nat
type max_message_size_t is nat
type state_hash_t is bytes
type addr_set_t is set(address)
type message_store_t is map(bytes,addr_set_t)
type proposal_counters_t is map(address,nat)
type storage_t is record
state_hash : state_hash_t ;
threshold : threshold_t ;
max_proposal : max_proposal_t ;
max_message_size : max_message_size_t ;
authorized_addresses : addr_set_t ;
message_store : message_store_t ;
proposal_counters : proposal_counters_t ;
end
type threshold is nat
type max_proposal is nat
type max_message_size is nat
type state_hash is bytes
type addr_set is set (address)
type message_store is map (bytes, addr_set)
type proposal_counters is map (address, nat)
type storage is
record [
state_hash : state_hash;
threshold : threshold;
max_proposal : max_proposal;
max_message_size : max_message_size;
authorized_addresses : addr_set;
message_store : message_store;
proposal_counters : proposal_counters
]
// I/O types
type message_t is (bytes -> list(operation))
type send_pt is message_t
type withdraw_pt is message_t
type message is bytes -> list (operation)
type send_pt is message
type withdraw_pt is message
type default_pt is unit
type contract_return_t is (list(operation) * storage_t)
type return is list (operation) * storage
type entry_point_t is
| Send of send_pt
type parameter is
Send of send_pt
| Withdraw of withdraw_pt
| Default of default_pt
| Default of default_pt
function send (const param : send_pt; const s : storage) : return is
block {
// check sender against the authorized addresses
function send (const param : send_pt; const s : storage_t) : contract_return_t is block {
if not set_mem (sender, s.authorized_addresses)
then failwith("Unauthorized address")
else skip;
// check sender against the authorized addresses
if not set_mem(sender,s.authorized_addresses) then failwith("Unauthorized address") else skip ;
// check message size against the stored limit
// check message size against the stored limit
var message : message_t := param ;
const packed_msg : bytes = bytes_pack(message) ;
if size(packed_msg) > s.max_message_size then failwith("Message size exceed maximum limit")
else skip ;
var message : message := param;
const packed_msg : bytes = bytes_pack (message);
if size (packed_msg) > s.max_message_size
then failwith ("Message size exceed maximum limit")
else skip;
// compute the new set of addresses associated with the message and update counters
var new_store : addr_set_t := set_empty ;
case map_get(packed_msg, s.message_store) of
| Some(voters) -> block { // the message is already stored
// increment the counter only if the sender isn't already associated with the message
if set_mem(sender,voters) then skip
else s.proposal_counters[sender] := get_force(sender,s.proposal_counters) + 1n ;
(* compute the new set of addresses associated with the message and
update counters *)
new_store := set_add(sender,voters)
}
| None -> block { // the message has never been received before
s.proposal_counters[sender] := get_force(sender,s.proposal_counters) + 1n ;
new_store := set [sender];
}
end ;
var new_store : addr_set := set_empty;
// check sender counters against the maximum number of proposal
var sender_proposal_counter : nat := get_force(sender,s.proposal_counters) ;
if sender_proposal_counter > s.max_proposal then failwith("Maximum number of proposal reached")
else skip ;
case map_get (packed_msg, s.message_store) of
Some (voters) ->
block {
(* The message is already stored.
Increment the counter only if the sender is not already
associated with the message. *)
if set_mem (sender, voters)
then skip
else s.proposal_counters[sender] :=
get_force (sender, s.proposal_counters) + 1n;
// check the threshold
var ret_ops : list(operation) := (nil : list(operation)) ;
if size(new_store) >= s.threshold then block {
remove packed_msg from map s.message_store ;
ret_ops := message(s.state_hash) ;
// update the state hash
s.state_hash := sha_256 ( bytes_concat (s.state_hash , packed_msg) ) ;
// decrement the counters
for addr -> ctr in map s.proposal_counters block {
if set_mem(addr,new_store) then
s.proposal_counters[addr] := abs (ctr - 1n)
else skip ;
}
} else
s.message_store[packed_msg] := new_store
} with ( ret_ops , s)
new_store := set_add(sender,voters)
}
| None ->
block {
// the message has never been received before
s.proposal_counters[sender] :=
get_force (sender, s.proposal_counters) + 1n;
new_store := set [sender]
}
end;
function withdraw (const param : withdraw_pt; const s : storage_t) : contract_return_t is block {
// check sender counters against the maximum number of proposal
var message : message_t := param ;
const packed_msg : bytes = bytes_pack(message) ;
var sender_proposal_counter : nat :=
get_force (sender, s.proposal_counters);
case map_get(packed_msg, s.message_store) of
| Some(voters) -> block { // the message is stored
const new_set : addr_set_t = set_remove(sender,voters) ;
if sender_proposal_counter > s.max_proposal
then failwith ("Maximum number of proposal reached")
else skip;
// decrement the counter only if the sender was already associated with the message
if size(voters) =/= size(new_set) then
s.proposal_counters[sender] := abs (get_force(sender,s.proposal_counters) - 1n)
else skip ;
// check the threshold
// if the message is left without any associated addresses, remove the corresponding message_store field
if size(new_set) = 0n then remove packed_msg from map s.message_store
else s.message_store[packed_msg] := new_set
}
| None -> skip end // the message isn't stored, ignore
var ret_ops : list (operation) := nil;
} with ( (nil: list(operation)) , s)
if size (new_store) >= s.threshold then {
remove packed_msg from map s.message_store;
ret_ops := message (s.state_hash);
// update the state hash
s.state_hash := sha_256 (bytes_concat (s.state_hash, packed_msg));
// decrement the counters
for addr -> ctr in map s.proposal_counters block {
if set_mem(addr,new_store) then
s.proposal_counters[addr] := abs (ctr - 1n)
else skip
}
} else s.message_store[packed_msg] := new_store
} with (ret_ops, s)
function default (const p : default_pt; const s : storage_t) : contract_return_t is
((nil: list(operation)) , s)
function withdraw (const param : withdraw_pt; const s : storage) : return is
block {
var message : message := param;
const packed_msg : bytes = bytes_pack (message);
function main(const param : entry_point_t; const s : storage_t) : contract_return_t is
case map_get(packed_msg, s.message_store) of
Some (voters) ->
block {
// The message is stored
const new_set : addr_set = set_remove (sender, voters);
(* Decrement the counter only if the sender was already
associated with the message *)
if size (voters) =/= size (new_set)
then s.proposal_counters[sender] :=
abs (get_force (sender, s.proposal_counters) - 1n)
else skip ;
(* If the message is left without any associated addresses,
remove the corresponding message_store field *)
if size (new_set) = 0n
then remove packed_msg from map s.message_store
else s.message_store[packed_msg] := new_set
}
| None -> skip
end // The message is not stored, ignore.
} with ((nil : list (operation)), s)
function default (const p : default_pt; const s : storage) : return is
((nil : list (operation)), s)
function main (const param : parameter; const s : storage) : return is
case param of
// propagate message p if the number authorized addresses having
// voted for the same message p equals the threshold
| Send (p) -> send(p,s)
// withraw vote for message p
| Withdraw (p) -> withdraw(p,s)
// use this entry-point to transfer tez to the contract
| Default (p) -> default(p,s)
end
(* Propagate message p if the number of authorized addresses having
voted for the same message p equals the threshold. *)
| Send (p) -> send (p, s)
(* Withraw vote for message p *)
| Withdraw (p) -> withdraw (p, s)
(* Use this action to transfer tez to the contract *)
| Default (p) -> default (p, s)
end

View File

@ -1,62 +1,66 @@
// storage type
type counter_t is nat
type threshold_t is nat
type authorized_keys_t is list(key)
type id_t is string
type storage_t is record
id : id_t ;
counter : counter_t ;
threshold : threshold_t ;
auth : authorized_keys_t ;
end
type counter is nat
type threshold is nat
type authorized_keys is list (key)
type id is string
type storage is
record [
id : id;
counter : counter;
threshold : threshold;
auth : authorized_keys
]
// I/O types
type message_t is (unit -> list(operation))
type signatures_t is list(key_hash * signature)
type check_message_pt is record
counter : counter_t ;
message : message_t ;
signatures : signatures_t ;
end
type contract_return_t is (list(operation) * storage_t)
type message is unit -> list (operation)
type entry_point_t is
| CheckMessage of check_message_pt
type signatures is list (key_hash * signature)
type check_message_pt is
record [
counter : counter;
message : message;
signatures : signatures
]
type return is list (operation) * storage
type parameter is CheckMessage of check_message_pt
function check_message (const param : check_message_pt;
const s : storage_t) : contract_return_t is block {
var message : message_t := param.message ;
const s : storage) : return is block {
var message : message := param.message;
if param.counter =/= s.counter then
failwith ("Counters does not match")
else block {
else {
const packed_payload : bytes =
bytes_pack((message , param.counter , s.id , get_chain_id));
var valid : nat := 0n ;
bytes_pack ((message, param.counter, s.id, get_chain_id));
var valid : nat := 0n;
var keys : authorized_keys_t := s.auth ;
var keys : authorized_keys := s.auth;
for pkh_sig in list param.signatures block {
case keys of
| nil -> skip
nil -> skip
| key # tl -> block {
keys := tl ;
if pkh_sig.0 = crypto_hash_key(key) then
if crypto_check(key,pkh_sig.1,packed_payload) then valid := valid + 1n ;
else failwith ("Invalid signature")
else skip;
}
keys := tl;
if pkh_sig.0 = crypto_hash_key (key) then
if crypto_check (key, pkh_sig.1, packed_payload)
then valid := valid + 1n
else failwith ("Invalid signature")
else skip
}
end
};
if valid < s.threshold then
failwith ("Not enough signatures passed the check")
else s.counter := s.counter + 1n ;
else s.counter := s.counter + 1n
}
} with (message(unit), s)
} with (message (unit), s)
function main(const param : entry_point_t; const s : storage_t) : contract_return_t is
case param of
| CheckMessage (p) -> check_message(p,s)
end
function main (const param : parameter; const s : storage) : return is
case param of CheckMessage (p) -> check_message (p,s) end

View File

@ -17,7 +17,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 python3 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

View File

@ -1,36 +0,0 @@
lib: [
"_build/install/default/lib/UnionFind/META"
"_build/install/default/lib/UnionFind/Partition.cmi"
"_build/install/default/lib/UnionFind/Partition.cmti"
"_build/install/default/lib/UnionFind/Partition.mli"
"_build/install/default/lib/UnionFind/Partition0.cmi"
"_build/install/default/lib/UnionFind/Partition0.cmt"
"_build/install/default/lib/UnionFind/Partition0.cmx"
"_build/install/default/lib/UnionFind/Partition0.ml"
"_build/install/default/lib/UnionFind/Partition1.cmi"
"_build/install/default/lib/UnionFind/Partition1.cmt"
"_build/install/default/lib/UnionFind/Partition1.cmx"
"_build/install/default/lib/UnionFind/Partition1.ml"
"_build/install/default/lib/UnionFind/Partition2.cmi"
"_build/install/default/lib/UnionFind/Partition2.cmt"
"_build/install/default/lib/UnionFind/Partition2.cmx"
"_build/install/default/lib/UnionFind/Partition2.ml"
"_build/install/default/lib/UnionFind/Partition3.cmi"
"_build/install/default/lib/UnionFind/Partition3.cmt"
"_build/install/default/lib/UnionFind/Partition3.cmx"
"_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"
]
doc: [
"_build/install/default/doc/UnionFind/LICENSE"
"_build/install/default/doc/UnionFind/README.md"
]