├── .gitignore ├── .merlin ├── .travis.yml ├── LICENSE ├── README.md ├── _tags ├── bin ├── bash_completion.sh ├── build_FTP_example.sh ├── cav15-generate.sh ├── count-inst ├── generate-smtlib-benchmarks ├── line-counter.py ├── osx_gnu.sh ├── regression-tests ├── run-tests ├── run-tests-methods ├── xp_cav14.sh ├── xp_oopsla19.sh ├── xp_pldi20.sh └── xp_tacas14.sh ├── build.sh ├── emacs-mode ├── flycheck.el ├── spl-mode.el └── spl-mode.el.tmp ├── lib ├── console.c ├── console.spl ├── file.c ├── file.h ├── file.spl ├── fork.spl ├── makeStr.c ├── makeStr.spl ├── socket.c └── socket.spl ├── logo.png ├── src ├── backends │ ├── c │ │ ├── predef.ml │ │ ├── removeGhost.ml │ │ └── splCompiler.ml │ └── smtlib │ │ ├── smtLibLexer.mll │ │ ├── smtLibParser.mly │ │ ├── smtLibSolver.ml │ │ └── smtLibSyntax.ml ├── formulas │ ├── grass.ml │ ├── grassUtil.ml │ ├── sl.ml │ ├── slToGrass.ml │ └── slUtil.ml ├── frontends │ └── spl │ │ ├── splChecker.ml │ │ ├── splErrors.ml │ │ ├── splLexer.mll │ │ ├── splParser.mly │ │ ├── splSyntax.ml │ │ ├── splTranslator.ml │ │ └── splTypeChecker.ml ├── main │ ├── config.ml │ ├── grasshopper.ml │ └── vizmodel.ml ├── programs │ ├── prog.ml │ └── progError.ml ├── prover │ ├── axioms.ml │ ├── congruenceClosure.ml │ ├── congruenceClosureOld.ml │ ├── eMatching.ml │ ├── model.ml │ ├── modelPrinting.ml │ ├── modelRepl.ml │ ├── prover.ml │ ├── reduction.ml │ ├── simplifyGrass.ml │ └── typeStrat.ml ├── util │ ├── bloomFilter.ml │ ├── bloomFilter.mli │ ├── debug.ml │ ├── graph.ml │ ├── graph.mli │ ├── logger.ml │ ├── logger.mli │ ├── logging.ml │ ├── parray.ml │ ├── parray.mli │ ├── parseError.ml │ ├── prioQueue.ml │ ├── prioQueue.mli │ ├── puf.ml │ ├── puf.mli │ ├── symbolTbl.ml │ └── util.ml └── verifier │ ├── analyzer.ml │ ├── grassifier.ml │ ├── simplifier.ml │ ├── symbExec.ml │ ├── symbState.ml │ └── verifier.ml ├── tests ├── spl │ ├── abstract_preds │ │ └── simple.spl │ ├── adt │ │ ├── interfaces.spl │ │ ├── lists.spl │ │ └── pairs.spl │ ├── array │ │ ├── bsearch.spl │ │ ├── bubble.spl │ │ ├── checkSorted.spl │ │ ├── clamp.spl │ │ ├── copy.spl │ │ ├── copyByte.spl │ │ ├── copy_byte_slice.spl │ │ ├── destroy.spl │ │ ├── free.spl │ │ ├── initialize.spl │ │ ├── maximum.spl │ │ ├── quicksort.spl │ │ ├── quicksort_bound_only.spl │ │ ├── quicksort_distinct.spl │ │ ├── reverse.spl │ │ ├── selection_sort.spl │ │ ├── string.spl │ │ ├── test.spl │ │ └── traverse_with_nodes.spl │ ├── assoc │ │ ├── contains.spl │ │ ├── insert.spl │ │ ├── lookup.spl │ │ └── remove.spl │ ├── bitvector │ │ ├── arithmetic.spl │ │ └── intToByteArray.spl │ ├── bugs │ │ └── seg_fault_find_term.spl │ ├── c_compiler │ │ ├── int_array.c │ │ ├── int_array.spl │ │ ├── proc0.c │ │ ├── proc0.spl │ │ ├── proc1.c │ │ ├── proc1.spl │ │ ├── proc2.c │ │ ├── proc2.spl │ │ ├── proc3.c │ │ ├── proc3.spl │ │ ├── proc4.c │ │ ├── proc4.spl │ │ ├── proc5.c │ │ ├── proc5.spl │ │ ├── struct0.c │ │ ├── struct0.spl │ │ ├── struct1.c │ │ ├── struct1.spl │ │ ├── struct2.c │ │ ├── struct2.spl │ │ ├── struct3.c │ │ ├── struct3.spl │ │ ├── struct4.c │ │ ├── struct4.spl │ │ ├── struct5.c │ │ ├── struct5.spl │ │ ├── struct6.c │ │ └── struct6.spl │ ├── concurrent │ │ ├── array_util.spl │ │ ├── b+-tree.spl │ │ ├── flows-relational.spl │ │ ├── flows.spl │ │ ├── give-up-header.spl │ │ ├── give-up.spl │ │ ├── harris-1.spl │ │ ├── harris-2.spl │ │ ├── hashtbl.spl │ │ ├── link-header.spl │ │ ├── link.spl │ │ ├── list-flows-iterated.spl │ │ ├── lock_coupling_wo_flows │ │ │ ├── list_lock_coupling.spl │ │ │ └── list_no_content.spl │ │ ├── sl.spl │ │ ├── sls.spl │ │ ├── test_soundness1.spl │ │ ├── tests.spl │ │ └── threaded-tree.spl │ ├── counter │ │ ├── counter_simple.spl │ │ ├── counter_two_cells.spl │ │ └── counter_very_simple.spl │ ├── dl │ │ ├── dl_concat.spl │ │ ├── dl_copy.spl │ │ ├── dl_dancing.spl │ │ ├── dl_dancing_simple.spl │ │ ├── dl_dispose.spl │ │ ├── dl_filter.spl │ │ ├── dl_insert.spl │ │ ├── dl_remove.spl │ │ ├── dl_reverse.spl │ │ ├── dl_test.spl │ │ └── dl_traverse.spl │ ├── entailments │ │ ├── bounded_lists.spl │ │ └── entailments.spl │ ├── flows │ │ ├── array_util.spl │ │ ├── b+-tree.spl │ │ ├── b-link-core-old.spl │ │ ├── b-link-core.spl │ │ ├── b-link-full-old.spl │ │ ├── b-link-full.spl │ │ ├── b-link-half-old.spl │ │ ├── b-link-half.spl │ │ ├── ccm.spl │ │ ├── css.spl │ │ ├── flows.spl │ │ ├── give-up.spl │ │ ├── hashtbl-give-up.spl │ │ ├── hashtbl-link-simple.spl │ │ ├── hashtbl-link.spl │ │ ├── inset-flows.spl │ │ ├── link.spl │ │ ├── list-coupling.spl │ │ ├── lock-coupling.spl │ │ ├── multipair-ccm.spl │ │ ├── multiset-ccm.spl │ │ └── ordered_type.spl │ ├── ftp │ │ ├── askIP.spl │ │ ├── client.spl │ │ ├── doWeUpload.spl │ │ ├── response.spl │ │ └── server.spl │ ├── include │ │ ├── assoc_list.spl │ │ ├── bag.spl │ │ ├── bstree.spl │ │ ├── bstree_rec.spl │ │ ├── btree.spl │ │ ├── byte_array.spl │ │ ├── dllist.spl │ │ ├── int_array.spl │ │ ├── node_array.spl │ │ ├── ordered_type.spl │ │ ├── simple_int_array.spl │ │ ├── skiplist.spl │ │ ├── skiplistWithLength.spl │ │ ├── sllist.spl │ │ ├── sllist_rec.spl │ │ ├── slslist.spl │ │ ├── slsset.spl │ │ └── treeset.spl │ ├── lib_examples │ │ ├── consoleTest.spl │ │ ├── fileTest.spl │ │ ├── socketTcpReceiver.spl │ │ ├── socketTcpSender.spl │ │ ├── socketUdpReceiver.spl │ │ └── socketUdpSender.spl │ ├── link_and_array │ │ ├── hashset.spl │ │ ├── hashset_no_content.spl │ │ ├── hashset_no_content_ownership.spl │ │ ├── hashset_ownership.spl │ │ └── sllist_next_test.spl │ ├── list_set │ │ ├── contains.spl │ │ ├── delete.spl │ │ ├── difference.spl │ │ ├── insert.spl │ │ ├── intersect.spl │ │ ├── split.spl │ │ ├── traverse.spl │ │ └── union.spl │ ├── multi_copy │ │ ├── flows.spl │ │ ├── multi_copy_iterated.spl │ │ ├── multi_copy_new.spl │ │ └── ordered_type.spl │ ├── nested_sl │ │ ├── abstract_nested_sl.spl │ │ ├── create.spl │ │ ├── destroy.spl │ │ ├── insert.spl │ │ ├── nested_def.spl │ │ ├── nested_def2.spl │ │ ├── remove.spl │ │ └── traverse.spl │ ├── recursive_defs │ │ ├── bstree.spl │ │ ├── list.spl │ │ ├── list_length.spl │ │ └── treeset.spl │ ├── reloc │ │ ├── array_util.spl │ │ ├── b+-tree-split.spl │ │ ├── b+-tree.spl │ │ ├── b-link-half-split.spl │ │ ├── b-link-ind.spl │ │ ├── b-link-old.spl │ │ ├── b-link-weak.spl │ │ ├── b-link.spl │ │ ├── flows-relational.spl │ │ ├── flows.spl │ │ ├── give-up-header.spl │ │ ├── give-up.spl │ │ ├── harris-1.spl │ │ ├── harris-2.spl │ │ ├── hashtbl-give-up.spl │ │ ├── hashtbl.spl │ │ ├── link.spl │ │ ├── list-coupling-noinst.spl │ │ ├── list-coupling.spl │ │ ├── sl.spl │ │ ├── sls.spl │ │ ├── test_soundness1.spl │ │ ├── tests.spl │ │ └── threaded-tree.spl │ ├── sentinel_sl │ │ ├── clear.spl │ │ ├── concat.spl │ │ ├── copy.spl │ │ ├── filter.spl │ │ ├── insert.spl │ │ ├── remove.spl │ │ ├── reverse.spl │ │ ├── ssllist.spl │ │ └── traverse.spl │ ├── simple_arrays │ │ ├── bubble.spl │ │ ├── copy.spl │ │ ├── free.spl │ │ └── initialize.spl │ ├── sl │ │ ├── fpcheck.spl │ │ ├── rec_concat.spl │ │ ├── rec_copy.spl │ │ ├── rec_dispose.spl │ │ ├── rec_filter.spl │ │ ├── rec_insert.spl │ │ ├── rec_remove.spl │ │ ├── rec_reverse.spl │ │ ├── rec_traverse.spl │ │ ├── sl_concat.spl │ │ ├── sl_copy.spl │ │ ├── sl_dispose.spl │ │ ├── sl_filter.spl │ │ ├── sl_insert.spl │ │ ├── sl_remove.spl │ │ ├── sl_reverse.spl │ │ ├── sl_traverse.spl │ │ └── union_find.spl │ ├── sls │ │ ├── sls_concat.spl │ │ ├── sls_copy.spl │ │ ├── sls_dispose.spl │ │ ├── sls_double_all.spl │ │ ├── sls_filter.spl │ │ ├── sls_insert.spl │ │ ├── sls_insertion_sort.spl │ │ ├── sls_merge_sort.spl │ │ ├── sls_pairwise_sum.spl │ │ ├── sls_quicksort.spl │ │ ├── sls_quicksort_wo_split_impl.spl │ │ ├── sls_remove.spl │ │ ├── sls_reverse.spl │ │ ├── sls_strand_sort.spl │ │ └── sls_traverse.spl │ ├── sorted_array_util │ │ └── array_util.spl │ ├── soundness │ │ ├── soundness0.spl │ │ ├── soundness1.spl │ │ ├── soundness2.spl │ │ ├── soundness3.spl │ │ ├── soundness4.spl │ │ ├── soundness5.spl │ │ ├── soundness6.spl │ │ ├── soundness7.spl │ │ ├── soundness8.spl │ │ └── soundness9.spl │ ├── symb_exec │ │ ├── array.spl │ │ ├── basic.spl │ │ ├── dirty.spl │ │ ├── frame.spl │ │ ├── list.spl │ │ ├── soundness.spl │ │ └── soundness_arr1.spl │ ├── symb_exec_v2 │ │ └── basic.spl │ ├── tree │ │ ├── binary_search_tree.spl │ │ ├── binary_search_tree_no_content.spl │ │ ├── binary_search_tree_shape_only.spl │ │ ├── binary_search_tree_shape_only_tailrec.spl │ │ ├── binary_search_tree_tailrec.spl │ │ ├── skew_heap │ │ │ ├── extractMax.spl │ │ │ ├── insert.spl │ │ │ └── union.spl │ │ ├── skew_heap_no_content.spl │ │ ├── tree_to_list.spl │ │ └── union_find.spl │ ├── uninterpreted_datat_set │ │ ├── hashset.spl │ │ └── insert.spl │ └── work_in_progress │ │ ├── array │ │ └── csr.spl │ │ ├── bag_test.spl │ │ ├── link_and_array │ │ ├── btree │ │ │ ├── add.spl │ │ │ ├── array_utils.spl │ │ │ ├── def.spl │ │ │ ├── find.spl │ │ │ ├── node_utils.spl │ │ │ └── remove.spl │ │ ├── btree_1.spl │ │ ├── btree_2.spl │ │ ├── btree_generic.spl │ │ ├── btree_simple.spl │ │ ├── btree_simple_array │ │ │ ├── add.spl │ │ │ ├── array_utils.spl │ │ │ ├── def.spl │ │ │ ├── def_local.spl │ │ │ ├── find.spl │ │ │ ├── node_utils.spl │ │ │ └── remove.spl │ │ ├── hashset_abstract.spl │ │ ├── hashset_abstract_simple.spl │ │ ├── hashset_no_content_abstract.spl │ │ ├── hashset_no_content_abstract_disjoint.spl │ │ ├── skiplist_1.spl │ │ ├── skiplist_2.spl │ │ ├── skiplist_simple.spl │ │ └── string_slset.spl │ │ ├── list_of_trees │ │ └── traverse.spl │ │ ├── sls │ │ └── sls_merge_sort_abstract.spl │ │ ├── tree │ │ ├── aa_tree.spl │ │ ├── avl_tree.spl │ │ ├── external_bst.spl │ │ ├── external_bst_shape_only.spl │ │ ├── llrb.spl │ │ ├── quadtree.spl │ │ ├── red_black_tree.spl │ │ ├── skew_heap.spl │ │ └── todo │ │ └── tree_of_lists │ │ └── traverse.spl └── test.spl └── vim ├── ftdetect └── spl.vim └── syntax └── spl.vim /.gitignore: -------------------------------------------------------------------------------- 1 | _build/ 2 | *.native 3 | *.smt2 4 | *.dot 5 | model.html 6 | out 7 | out.spl 8 | *.pdf 9 | *.png 10 | *~ 11 | *.o 12 | *.swp 13 | -------------------------------------------------------------------------------- /.merlin: -------------------------------------------------------------------------------- 1 | S src/** 2 | B _build/** 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | dist: xenial 3 | 4 | install: 5 | - wget https://github.com/Z3Prover/z3/releases/download/z3-4.8.7/z3-4.8.7-x64-ubuntu-16.04.zip -O ~/z3.zip 6 | - unzip ~/z3.zip -d ~/z3 7 | - z3 --version 8 | - wget https://raw.githubusercontent.com/ocaml/ocaml-ci-scripts/master/.travis-ocaml.sh 9 | - bash -ex .travis-ocaml.sh 10 | - opam install -y ocamlfind ocamlbuild 11 | - eval $(opam config env) 12 | 13 | cache: 14 | apt: true 15 | directories: 16 | - $HOME/.opam 17 | 18 | env: 19 | global: 20 | - OCAML_VERSION=4.07 21 | - PATH="$HOME/z3/z3-4.8.7-x64-ubuntu-16.04/bin/:$PATH" 22 | - OPAMVERBOSE=1 23 | - OPAMYES=true 24 | - OPAMKEEPBUILDDIR=true 25 | 26 | script: 27 | - bash build.sh 28 | - bash build.sh tests 29 | 30 | os: linux 31 | 32 | notifications: 33 | slack: 34 | rooms: 'grasshopper-tool:XSTpOLbUL9oeQcdiIZ5BFBpa' 35 | template: 36 | - "Build <%{build_url}|#%{build_number}> (<%{compare_url}|%{commit}>) of %{repository_slug}@%{branch} by %{author} %{result} in %{duration}" 37 | - "Commit message: %{commit_subject}" 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wies/grasshopper/80b86679d02ee5a5ab9851dadb1877d105884cc2/LICENSE -------------------------------------------------------------------------------- /_tags: -------------------------------------------------------------------------------- 1 | <**/*.ml>: annot, bin_annot 2 | -------------------------------------------------------------------------------- /bin/bash_completion.sh: -------------------------------------------------------------------------------- 1 | _grasshopper() 2 | { 3 | local cur prev words cword split 4 | _init_completion -s || return 5 | 6 | opts="-basedir -v -q -stats -lint -model -nulledges -trace -dumpghp -dumpvcs -dumpcores -procedure -typeonly -noverify -robust -nomodifiesopt -optreach -noreach -noep -fullep -noinst -termgen -nostratify -nofixedpoint -abspreds -splitlemmas -smtsolver -smtpatterns -smtsets -smtarrays -bitvector -simplearrays -compile -help --help" 7 | 8 | case "${prev}" in 9 | -smtsolver) 10 | COMPREPLY=( $(compgen -W "z3 cvc4 cvc4mf z3+cvc4 z3+cvc4mf cvc4+cvc4mf z3+cvc4+cvc4mf" -- ${cur}) ) 11 | return 0 12 | ;; 13 | -dumpghp) 14 | COMPREPLY=( $(compgen -W "0 1 2 3" -- ${cur}) ) 15 | return 0 16 | ;; 17 | -termgen) 18 | COMPREPLY=( $(compgen -W "1 2 3 4 5 6 7 8 9" -- ${cur}) ) 19 | return 0 20 | ;; 21 | esac 22 | case "${cur}" in 23 | -*) 24 | COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) 25 | return 0 26 | ;; 27 | *) 28 | _filedir 29 | return 0 30 | ;; 31 | esac 32 | 33 | } 34 | complete -F _grasshopper grasshopper.native 35 | 36 | # -procedure Only check the specified procedure 37 | # -termgen Number of rounds to run the term generation procedure 38 | # -smtsolver Choose SMT solver (z3, cvc4, cvc4mf), e.g., 'z3+cvc4mf' 39 | # -compile Compile SPL program to a C program outputed as a file with the given name. 40 | 41 | -------------------------------------------------------------------------------- /bin/build_FTP_example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SRC=tests/spl/ftp 4 | LIB=lib 5 | OUT=ftpCcode 6 | 7 | echo calling GRASShopper to produce the C files 8 | 9 | mkdir -p $OUT 10 | 11 | ./grasshopper.native -v -bitvector $SRC/client.spl -compile $OUT/ftpClient.c 12 | ./grasshopper.native -v -bitvector $SRC/server.spl -compile $OUT/ftpServer.c 13 | 14 | echo compiling the C files 15 | 16 | opts='--std=gnu99' 17 | 18 | gcc $opts -c $LIB/console.c -o $OUT/console.o 19 | gcc $opts -c $LIB/file.c -o $OUT/file.o 20 | gcc $opts -c $LIB/socket.c -o $OUT/socket.o 21 | gcc $opts -c $LIB/makeStr.c -o $OUT/makeStr.o 22 | gcc $opts -c $OUT/ftpClient.c -o $OUT/ftpClient.o 23 | gcc $opts -c $OUT/ftpServer.c -o $OUT/ftpServer.o 24 | gcc $OUT/console.o $OUT/file.o $OUT/socket.o $OUT/makeStr.o $OUT/ftpServer.o -o $OUT/ftpServer 25 | gcc $OUT/console.o $OUT/file.o $OUT/socket.o $OUT/makeStr.o $OUT/ftpClient.o -o $OUT/ftpClient 26 | 27 | -------------------------------------------------------------------------------- /bin/osx_gnu.sh: -------------------------------------------------------------------------------- 1 | [[ $OSTYPE =~ "darwin" ]] && { 2 | alias time=gtime 3 | alias date=gdate 4 | alias sed=gsed 5 | shopt -s expand_aliases 6 | } 7 | -------------------------------------------------------------------------------- /bin/run-tests-methods: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source bin/osx_gnu.sh 4 | 5 | PASSED=1 6 | 7 | ensure_verifies() 8 | { 9 | # Function. Parameter 1 is the return code 10 | # Para. 2 is the name of the benchmark. 11 | if [ "${1}" -ne "0" ]; then 12 | echo -e "\rFailed benchmark ${2}. " 13 | echo "*** ERROR: Benchmark ${2} expected to verify, but did not verify." 14 | PASSED=0 15 | else 16 | echo -ne "\rPassed benchmark ${2}. " 17 | fi 18 | } 19 | 20 | ensure_fails() 21 | { 22 | # Function. Parameter 1 is the return code 23 | # Para. 2 is the name of the benchmark. 24 | if [ "${1}" -ne "1" ]; then 25 | echo -e "\rFailed benchmark ${2}. " 26 | echo "*** SOUNDNESS ERROR ***************************************" 27 | echo "*** SOUNDNESS ERROR: Benchmark ${2} expected to fail, but verified!" 28 | echo "*** SOUNDNESS ERROR ***************************************" 29 | PASSED=0 30 | else 31 | echo -ne "\rPassed benchmark ${2}. " 32 | fi 33 | } 34 | 35 | run_test() 36 | { 37 | echo -ne "Checking benchmark ${1}..." 38 | ulimit -St 600 39 | ./grasshopper.native $2 -procedure $3 $OPTIONS 2> /dev/null 40 | res=$? 41 | ulimit -St unlimited 42 | if [ $4 == "pass" ]; then 43 | ensure_verifies $res $1 44 | else 45 | ensure_fails $res $1 46 | fi 47 | } 48 | 49 | while (( "$#" )); do 50 | # UNIX timestamp concatenated with nanoseconds 51 | T="$(date +%s%N)" 52 | run_test ${1} ${2} ${3} ${4} 53 | # Time interval in nanoseconds 54 | T="$(($(date +%s%N)-T))" 55 | # Seconds 56 | S="$((T/1000000000))" 57 | # Milliseconds 58 | M="$((T/1000000))" 59 | printf "%02d:%02d.%03d\n" "$((S/60%60))" "$((S%60))" "${M}" 60 | shift 61 | shift 62 | shift 63 | shift 64 | done 65 | if [ $PASSED == 1 ]; then 66 | echo "All tests passed." 67 | else 68 | echo "There were failing test cases." 69 | fi 70 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source bin/osx_gnu.sh 4 | 5 | set -e 6 | 7 | DIRS="-Is src/util,src/formulas,src/backends/smtlib,src/backends/c,src/programs,src/frontends/spl,src/prover,src/sl,src/verifier,src/main" 8 | TARGET="src/main/grasshopper src/main/vizmodel " 9 | FLAGS="-cflag -g -lflag -g -libs unix,str $DIRS" 10 | OCAMLBUILD=ocamlbuild 11 | 12 | ocb() 13 | { 14 | $OCAMLBUILD -use-ocamlfind $FLAGS $* 15 | } 16 | 17 | if [ $# -eq 0 ]; then 18 | action=native 19 | else 20 | action=$1; 21 | shift 22 | fi 23 | 24 | case $action in 25 | clean) ocb -clean; echo "" ;; 26 | native) ocb ${TARGET//" "/".native "} ;; 27 | byte) ocb ${TARGET//" "/".byte "} ;; 28 | all) ocb ${TARGET//" "/".native "} ${TARGET//" "/".byte "} ;; 29 | prof) ocb ${TARGET//" "/".p.native "} ;; 30 | tests) bin/regression-tests $@ ;; 31 | depend) echo "Not needed.";; 32 | smt-lib) bin/generate-smtlib-benchmarks $@ ;; 33 | *) echo "Unknown action $action";; 34 | esac; 35 | 36 | -------------------------------------------------------------------------------- /lib/console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * Preloaded Code 7 | */ 8 | 9 | typedef struct { 10 | int length; 11 | char arr[]; 12 | } SPLArray_char; 13 | 14 | /* 15 | * Procedures 16 | */ 17 | 18 | bool gputs(SPLArray_char* buffer) { 19 | bool null_terminated = false; 20 | for (int i = 0; i < buffer->length && !null_terminated; i++) { 21 | null_terminated = buffer->arr[i] != 0; 22 | } 23 | if (null_terminated) { 24 | return fputs(buffer->arr, stdout) >= 0; 25 | } else { 26 | char str[buffer->length + 1]; //allocate on the stack for simplicity 27 | memcpy(str, buffer->arr, buffer->length); 28 | str[buffer->length] = 0; 29 | return fputs(str, stdout) >= 0; 30 | } 31 | } 32 | 33 | int ggets(SPLArray_char* buffer) { 34 | if (fgets(buffer->arr, buffer->length, stdin) == NULL) { 35 | return -1; 36 | } else { 37 | return strnlen(buffer->arr, buffer->length); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/console.spl: -------------------------------------------------------------------------------- 1 | include "../tests/spl/include/byte_array.spl"; 2 | 3 | procedure gputs(buffer: Array) returns (success: Bool) 4 | requires byte_array(buffer) 5 | ensures byte_array(buffer) 6 | ensures buffer == old(buffer) 7 | ensures buffer.length == old(buffer.length) 8 | ensures forall i: Int :: i >= 0 && i <= buffer.length ==> buffer[i] == old(buffer[i]) 9 | 10 | procedure ggets(buffer: Array) returns (nChars: Int) 11 | requires byte_array(buffer) 12 | ensures byte_array(buffer) 13 | ensures buffer == old(buffer) 14 | ensures buffer.length == old(buffer.length) 15 | ensures nChars >= -1 && nChars <= buffer.length 16 | -------------------------------------------------------------------------------- /lib/file.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | /* 15 | * Preloaded Code 16 | */ 17 | 18 | typedef struct { 19 | int length; 20 | int arr[]; 21 | } SPLArray_int; 22 | 23 | typedef struct { 24 | int length; 25 | bool arr[]; 26 | } SPLArray_bool; 27 | 28 | typedef struct { 29 | int length; 30 | char arr[]; 31 | } SPLArray_char; 32 | 33 | typedef struct { 34 | int length; 35 | void* arr[]; 36 | } SPLArray_generic; 37 | 38 | /* 39 | * Procedures 40 | */ 41 | int gclose (int fd); 42 | int gopen (SPLArray_char* pathname, int flags); 43 | int gread (int fd_2, SPLArray_char* buffer); 44 | int greadOffset (int fd_3, SPLArray_char* buffer_1, int offset); 45 | int gwrite (int fd_4, SPLArray_char* buffer_2); 46 | int gwrite2 (int fd_4, SPLArray_char* buffer_2, int size); 47 | int fileSize (SPLArray_char* pathname); 48 | -------------------------------------------------------------------------------- /lib/fork.spl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | procedure fork() returns (result: Int) 5 | ensures result >= -1 6 | -------------------------------------------------------------------------------- /lib/makeStr.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int makeStrFromInt(int myInt){ 4 | char c = myInt + '0'; 5 | return c; 6 | } 7 | -------------------------------------------------------------------------------- /lib/makeStr.spl: -------------------------------------------------------------------------------- 1 | 2 | 3 | procedure makeStrFromInt(myInt: Int) returns (myByte: Byte) 4 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wies/grasshopper/80b86679d02ee5a5ab9851dadb1877d105884cc2/logo.png -------------------------------------------------------------------------------- /src/main/vizmodel.ml: -------------------------------------------------------------------------------- 1 | open Sl 2 | open Util 3 | open Logging 4 | 5 | let input_file = ref "" 6 | 7 | let usage_message = 8 | "Usage:\n " ^ Sys.argv.(0) ^ 9 | " [options]\n" 10 | 11 | let cmd_line_error msg = 12 | Arg.usage Config.cmd_options_spec usage_message; 13 | failwith ("Command line option error: " ^ msg) 14 | 15 | let parse_input file = 16 | let input = read_file file in 17 | ParseError.input := Some input; 18 | let lexbuf = Lexing.from_string input in 19 | ParseError.buffer := Some lexbuf; 20 | let input = ParseError.parse_buf_exn SmtLibParser.output SmtLibLexer.token lexbuf in 21 | match input with 22 | | SmtLibSyntax.Model cmds -> 23 | let session = SmtLibSolver.start "model" "sat" in 24 | let model = SmtLibSolver.convert_model session cmds in 25 | SmtLibSolver.quit session; 26 | model 27 | | _ -> failwith "Input file does not contain an SMT-LIB model" 28 | 29 | 30 | let vizmodel file = 31 | let model = parse_input file in 32 | let model_chan = open_out !Config.model_file in 33 | (* Model.print_model2 model;*) 34 | if Str.string_match (Str.regexp ".*\\.html$") !Config.model_file 0 then 35 | ModelPrinting.output_html model_chan (Model.complete model) Grass.TermSet.empty 36 | else 37 | ModelPrinting.output_graph model_chan (Model.complete model) Grass.TermSet.empty; 38 | close_out model_chan 39 | 40 | let _ = 41 | try 42 | Arg.parse Config.cmd_options_spec (fun s -> input_file := s) usage_message; 43 | SmtLibSolver.select_solver (String.uppercase_ascii !Config.smtsolver); 44 | if !input_file = "" 45 | then cmd_line_error "input file missing" 46 | else vizmodel !input_file 47 | with 48 | | Sys_error s -> 49 | output_string stderr (s ^ "\n"); 50 | exit 1 51 | | Failure s -> 52 | let bs = if Debug.is_debug 0 then Printexc.get_backtrace () else "" in 53 | output_string stderr (s ^ "\n" ^ bs); exit 1 54 | | Parsing.Parse_error -> 55 | print_endline "parse error"; 56 | exit 1 57 | | ProgError.Prog_error _ as e -> 58 | output_string stderr (ProgError.to_string e ^ "\n"); 59 | exit 1 60 | 61 | -------------------------------------------------------------------------------- /src/programs/progError.ml: -------------------------------------------------------------------------------- 1 | open Grass 2 | 3 | exception Prog_error of source_position * string 4 | 5 | let flycheck_string_of_src_pos pos = 6 | if pos.sp_start_line <> pos.sp_end_line 7 | then Printf.sprintf "%s:%d:%d" pos.sp_file pos.sp_start_line pos.sp_start_col 8 | else 9 | let start_col, end_col = 10 | if pos.sp_start_col = pos.sp_end_col 11 | then 12 | if pos.sp_start_col = 0 13 | then 0, 1 14 | else pos.sp_start_col - 1, pos.sp_end_col 15 | else pos.sp_start_col, pos.sp_end_col 16 | in 17 | Printf.sprintf "%s:%d:%d-%d" pos.sp_file pos.sp_start_line start_col end_col 18 | 19 | let lexical_error pos = raise (Prog_error (pos, "Lexical Error")) 20 | 21 | let syntax_error pos msg_opt = 22 | match msg_opt with 23 | | Some msg -> raise (Prog_error (pos, "Syntax Error: " ^ msg)) 24 | | None -> raise (Prog_error (pos, "Syntax Error")) 25 | 26 | let type_error pos msg = raise (Prog_error (pos, "Type Error: " ^ msg)) 27 | 28 | let error pos msg = raise (Prog_error (pos, "Error: " ^ msg)) 29 | 30 | let error_to_string pos msg = 31 | if pos = GrassUtil.dummy_position 32 | then msg 33 | else 34 | if !Config.flycheck_mode 35 | then Printf.sprintf "%s:%s" (flycheck_string_of_src_pos pos) msg 36 | else Printf.sprintf "%s:\n%s" (string_of_src_pos pos) msg 37 | 38 | let to_string = function 39 | | Prog_error (pos, msg) -> error_to_string pos msg 40 | | e -> raise (Invalid_argument "ProgError.to_string: expected a program error exception") 41 | 42 | let print_error pos msg = print_endline (to_string (Prog_error (pos, msg))) 43 | 44 | let mk_trace_info msg = "Trace Information: " ^ msg 45 | 46 | let mk_error_info msg = "Related Location: " ^ msg 47 | -------------------------------------------------------------------------------- /src/prover/typeStrat.ml: -------------------------------------------------------------------------------- 1 | open Util 2 | open Grass 3 | open GrassUtil 4 | 5 | let is_stratified t1 t2 = 6 | begin 7 | (*[ (Map (Loc, Bool), Bool); 8 | (Map (Loc, Loc), Loc); 9 | (Map (Loc, Int), Int); 10 | (Bool, Loc); 11 | (Loc, Int); 12 | (Loc, Set Loc); 13 | (Int, Set Int) ] *) 14 | match t1 with 15 | | Map ([Loc _], (Bool | Loc _)) -> 16 | begin 17 | match t2 with 18 | | Loc (FreeSrt ("Data", 0)) | Bool | Loc _ | Int | Set Int | Set (Loc _) -> true 19 | | _ -> false 20 | end 21 | | Map ([Loc _], Int) -> 22 | begin 23 | match t2 with 24 | | Loc (FreeSrt ("Data", 0)) | Bool | Int | Set Int -> true 25 | | _ -> false 26 | end 27 | | Loc _ -> 28 | begin 29 | match t2 with 30 | | Loc (FreeSrt ("Data", 0)) | Bool | Int | Set (Loc _) -> true 31 | | _ -> false 32 | end 33 | | Bool -> true 34 | | Int -> 35 | begin 36 | match t2 with 37 | | Loc (FreeSrt ("Data", 0)) | Bool | Set Int -> true 38 | | _ -> false 39 | end 40 | | _ -> t2 = Bool || t2 = Loc (FreeSrt ("Data", 0)) 41 | end 42 | 43 | -------------------------------------------------------------------------------- /src/util/bloomFilter.ml: -------------------------------------------------------------------------------- 1 | (** Bloom Filters for Approximate Sets. 2 | 3 | The implementation is geared towards efficiency at the risk of 4 | potentially larger false positive rates for membership queries. It 5 | uses fixed sized bit arrays that fit into OCaml's int values. So the 6 | implementation is platform-dependant. 7 | 8 | *) 9 | 10 | (** The type of approximate sets. *) 11 | type 'a t = int 12 | 13 | (** Size of bit array. *) 14 | let max = Sys.int_size 15 | 16 | (** Compute hash of [x]. *) 17 | let hash (x: 'a) = 18 | Hashtbl.hash x 19 | 20 | (** Compute hash of [x] with added 'salt' [salt] *) 21 | let hash_with_salt (x: 'a) (salt: int): int = 22 | hash (salt + hash x) 23 | 24 | (** The empty set. *) 25 | let empty: 'a t = 0 26 | 27 | (** Compute index of [x] into bit array. *) 28 | let get_index x = 29 | let rec get_index h salt = 30 | if h = max then get_index (hash_with_salt x salt land max) (salt + 1) else h 31 | in 32 | get_index (hash x land max) 1 33 | 34 | (** Create the singleton approximate from element [x]. *) 35 | let singleton x = 36 | let index = get_index x in 37 | 1 lsl index 38 | 39 | (** Insert [x] into approximate set [xs]. *) 40 | let add (x: 'a) (xs: 'a t) = 41 | let index = get_index x in 42 | xs lor (1 lsl index) 43 | 44 | (** Compute intersection of approximate sets [xs] and [ys]. *) 45 | let inter (xs: 'a t) (ys: 'a t) = xs land ys 46 | 47 | (** Compute union of approximate sets [xs] and [ys]. *) 48 | let union (xs: 'a t) (ys: 'a t) = xs lor ys 49 | 50 | (** Check whether [x] is contained in approximate set [xs]. *) 51 | let mem (x: 'a) (xs: 'a t): bool = 52 | let index = get_index x in 53 | xs land (1 lsl index) <> 0 54 | -------------------------------------------------------------------------------- /src/util/bloomFilter.mli: -------------------------------------------------------------------------------- 1 | (** Bloom Filters for Approximate Sets. 2 | 3 | The implementation is geared towards efficiency at the risk of 4 | potentially larger false positive rates for membership queries. It 5 | uses fixed sized bit array that fit into OCaml's int values. So the 6 | implementation is platform-dependant. 7 | 8 | *) 9 | 10 | (** The type of approximate sets. *) 11 | type 'a t 12 | 13 | (** The empty set. *) 14 | val empty: 'a t 15 | 16 | (** Create the singleton approximate set from given element. *) 17 | val singleton: 'a -> 'a t 18 | 19 | (** Insert element into an approximate set. *) 20 | val add: 'a -> 'a t -> 'a t 21 | 22 | (** Compute intersection of two approximate sets. *) 23 | val inter: 'a t -> 'a t -> 'a t 24 | 25 | (** Compute union of two approximate sets. *) 26 | val union: 'a t -> 'a t -> 'a t 27 | 28 | (** Check whether elemet is contained in an approximate set. *) 29 | val mem: 'a -> 'a t -> bool 30 | -------------------------------------------------------------------------------- /src/util/debug.ml: -------------------------------------------------------------------------------- 1 | type level = NONE | FATAL | ERROR | WARN | NOTICE | INFO | DEBUG of int 2 | 3 | let int_of_level = function 4 | | NONE -> 0 | FATAL -> 1 | ERROR -> 2 | WARN -> 3 5 | | NOTICE -> 4 | INFO -> 5 | DEBUG l -> 6 + l 6 | 7 | let level_of_int = function 8 | | 0 -> NONE | 1 -> FATAL | 2 -> ERROR | 3 -> WARN 9 | | 4 -> NOTICE | 5 -> INFO | l when l > 5 -> DEBUG (l - 6) 10 | | i -> failwith ("invalid level: " ^ string_of_int i) 11 | 12 | let lv = ref (int_of_level NOTICE) 13 | 14 | let set_level lvl = 15 | lv := int_of_level lvl; 16 | match lvl with 17 | | DEBUG _ -> Printexc.record_backtrace true 18 | | _ -> Printexc.record_backtrace false 19 | 20 | let show lvl = !lv >= (int_of_level lvl) 21 | 22 | let is_debug l = show (DEBUG l) 23 | let is_info () = show INFO 24 | let is_notice () = show NOTICE 25 | let is_warn () = show WARN 26 | let is_error () = show ERROR 27 | 28 | let more_verbose () = 29 | let nlv = match (level_of_int !lv) with 30 | | DEBUG l -> DEBUG (l + 1) 31 | | INFO -> DEBUG 0 32 | | NOTICE -> INFO 33 | | WARN -> NOTICE 34 | | ERROR -> WARN 35 | | FATAL -> ERROR 36 | | NONE -> FATAL 37 | in 38 | set_level nlv 39 | 40 | let less_verbose () = 41 | let nlv = match (level_of_int !lv) with 42 | | DEBUG 0 -> INFO 43 | | DEBUG l -> DEBUG (l - 1) 44 | | INFO -> NOTICE 45 | | NOTICE -> WARN 46 | | WARN -> ERROR 47 | | ERROR -> FATAL 48 | | FATAL -> NONE 49 | | NONE -> NONE 50 | in 51 | set_level nlv 52 | 53 | 54 | (** always print this message *) 55 | let amsg s = 56 | print_string s; flush_all () 57 | 58 | let debug s = if show (DEBUG 0) then amsg (s ()) 59 | let debugl l s = if show (DEBUG l) then amsg (s ()) 60 | let info s = if show INFO then amsg (s ()) 61 | let notice s = if show NOTICE then amsg (s ()) 62 | let warn s = if show WARN then amsg (s ()) 63 | let error s = if show ERROR then amsg (s ()) 64 | 65 | let phase s fn x = 66 | debug (fun () -> s () ^ "..."); 67 | let res = fn x in 68 | debug (fun () -> "done.\n"); 69 | res 70 | -------------------------------------------------------------------------------- /src/util/graph.mli: -------------------------------------------------------------------------------- 1 | module type Vertex = sig 2 | type t 3 | 4 | val compare: t -> t -> int 5 | 6 | val hash: t -> int 7 | 8 | val equal: t -> t -> bool 9 | end 10 | 11 | module Make(V: Vertex)(VertexSet: Set.S with type elt = V.t): sig 12 | type t 13 | 14 | type vertex = V.t 15 | 16 | val empty: t 17 | 18 | val vertices: t -> VertexSet.t 19 | 20 | val add_vertex: t -> vertex -> t 21 | 22 | val add_edge: t -> vertex -> vertex -> t 23 | 24 | val add_edges: t -> vertex -> VertexSet.t -> t 25 | 26 | val topsort: t -> vertex list list 27 | end 28 | -------------------------------------------------------------------------------- /src/util/logging.ml: -------------------------------------------------------------------------------- 1 | open Logger 2 | 3 | let _ = Logger.init [("Prover", WARN); ("Main", DEBUG); ("SmtLib", DEBUG)] dbg_formatter 4 | 5 | 6 | let main_log = make_log "Main" 7 | let prover_log = make_log "Prover" 8 | let smtlib_log = make_log "SmtLib" 9 | -------------------------------------------------------------------------------- /src/util/parray.mli: -------------------------------------------------------------------------------- 1 | (**************************************************************************) 2 | (* *) 3 | (* Copyright (C) Jean-Christophe Filliatre *) 4 | (* *) 5 | (* This software is free software; you can redistribute it and/or *) 6 | (* modify it under the terms of the GNU Library General Public *) 7 | (* License version 2.1, with the special exception on linking *) 8 | (* described in file LICENSE. *) 9 | (* *) 10 | (* This software is distributed in the hope that it will be useful, *) 11 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 12 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 13 | (* *) 14 | (**************************************************************************) 15 | 16 | (* Persistent arrays *) 17 | 18 | type 'a t 19 | 20 | val create : int -> 'a -> 'a t 21 | 22 | val init : int -> (int -> 'a) -> 'a t 23 | 24 | val length : 'a t -> int 25 | 26 | val get : 'a t -> int -> 'a 27 | 28 | val set : 'a t -> int -> 'a -> 'a t 29 | 30 | val to_list : 'a t -> 'a list 31 | 32 | val iter : ('a -> unit) -> 'a t -> unit 33 | val iteri : (int -> 'a -> unit) -> 'a t -> unit 34 | 35 | val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'a 36 | val fold_right : ('a -> 'b -> 'b) -> 'a t -> 'b -> 'b 37 | 38 | -------------------------------------------------------------------------------- /src/util/parseError.ml: -------------------------------------------------------------------------------- 1 | (** Auxiliary file used to avoid module recursion, 2 | stores error handling routing for the generated {!Stmnt.path} parser. *) 3 | 4 | open Lexing 5 | 6 | type bufp = Lexing.lexbuf option ref 7 | 8 | let (input : string option ref) = ref None 9 | let (buffer : bufp) = ref None 10 | 11 | let marker = " <*> " 12 | 13 | let parse_error s = match !input with 14 | | Some inp -> (match !buffer with 15 | | Some buf -> 16 | let pos = buf.lex_curr_p.pos_cnum in 17 | let init = String.sub inp 0 pos in 18 | let rest = String.sub inp pos (String.length inp - pos) in 19 | output_string stderr ("Parse error:\n" ^ init ^ marker ^ rest ^ "\n") 20 | | _ -> output_string stderr ("Parse error in uninitialized parse state1.\n")) 21 | | _ -> output_string stderr ("Parse error in uninitialized parse state.\n") 22 | 23 | let parse_buf_exn rule lexer lexbuf = 24 | try 25 | rule lexer lexbuf 26 | with exn -> 27 | begin 28 | parse_error ""; 29 | exit 1 30 | end 31 | -------------------------------------------------------------------------------- /src/util/prioQueue.mli: -------------------------------------------------------------------------------- 1 | (** Priority Search Queues. 2 | 3 | Implements the data structure from this paper: 4 | A Simple Implementation Technique for Priority Search Queues 5 | Ralf Hinze, ICFP 2001 6 | *) 7 | 8 | module type OrderedType = sig 9 | type t 10 | val compare: t -> t -> int 11 | end 12 | 13 | module Make(K: OrderedType)(P: OrderedType): sig 14 | 15 | type t 16 | 17 | val empty: t 18 | 19 | val is_empty: t -> bool 20 | (* runs in O(1) *) 21 | 22 | val size: t -> int 23 | (* runs in O(1) *) 24 | 25 | val insert: K.t -> P.t -> t -> t 26 | (* runs in O(log n) *) 27 | 28 | val delete: K.t -> t -> t 29 | (* runs in O(log n) *) 30 | 31 | val min: t -> K.t * P.t 32 | (* runs in O(1) *) 33 | 34 | val extract_min: t -> K.t * P.t * t 35 | (* runs in O(log n) *) 36 | 37 | val adjust: (P.t -> P.t) -> K.t -> t -> t 38 | (* runs in O(log n) *) 39 | 40 | val find_opt: K.t -> t -> P.t option 41 | 42 | val fold: (K.t -> P.t -> 'a -> 'a) -> t -> 'a -> 'a 43 | 44 | val exists: (K.t -> P.t -> bool) -> t -> bool 45 | 46 | val forall: (K.t -> P.t -> bool) -> t -> bool 47 | end 48 | -------------------------------------------------------------------------------- /src/util/puf.mli: -------------------------------------------------------------------------------- 1 | (**************************************************************************) 2 | (* *) 3 | (* Copyright (C) Jean-Christophe Filliatre *) 4 | (* *) 5 | (* This software is free software; you can redistribute it and/or *) 6 | (* modify it under the terms of the GNU Library General Public *) 7 | (* License version 2.1, with the special exception on linking *) 8 | (* described in file LICENSE. *) 9 | (* *) 10 | (* This software is distributed in the hope that it will be useful, *) 11 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 12 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 13 | (* *) 14 | (**************************************************************************) 15 | 16 | (* A persistent union-find data structure. 17 | 18 | The datatype [t] maintains a partition of the set [0,1,...,n-1], 19 | where [n] is the value passed to [create]. *) 20 | 21 | type t 22 | 23 | val create : int -> t 24 | 25 | val find : t -> int -> int 26 | 27 | val union : t -> int -> int -> t 28 | -------------------------------------------------------------------------------- /src/util/symbolTbl.ml: -------------------------------------------------------------------------------- 1 | open Util 2 | 3 | type t = (Grass.ident Grass.IdMap.t) list 4 | 5 | let empty = [Grass.IdMap.empty] 6 | 7 | let push tbl = Grass.IdMap.empty :: tbl 8 | 9 | let pop tbl = List.tl tbl 10 | 11 | let add tbl name id = 12 | Grass.IdMap.add name id (List.hd tbl) :: List.tl tbl 13 | 14 | let remove tbl name = 15 | Grass.IdMap.remove name (List.hd tbl) :: List.tl tbl 16 | 17 | let declared_in_current tbl name = 18 | Grass.IdMap.mem name (List.hd tbl) 19 | 20 | let find_local tbl name = 21 | match tbl with 22 | | [] -> None 23 | | t :: _ -> 24 | try Some (Grass.IdMap.find name t) 25 | with Not_found -> None 26 | 27 | let find tbl name = 28 | let rec find = function 29 | | [] -> None 30 | | t :: ts -> 31 | try Some (Grass.IdMap.find name t) 32 | with Not_found -> find ts 33 | in find tbl 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /tests/spl/abstract_preds/simple.spl: -------------------------------------------------------------------------------- 1 | struct T { 2 | var g: T; 3 | } 4 | 5 | struct S {} 6 | 7 | predicate p(x: T) 8 | 9 | procedure bar(x: T) 10 | requires p(x) 11 | ensures emp 12 | 13 | procedure foo(x: T, y: T) 14 | requires p(x) &*& p(y) 15 | ensures p(y) 16 | { 17 | bar(x); 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /tests/spl/adt/interfaces.spl: -------------------------------------------------------------------------------- 1 | struct Node { 2 | var next: Node; 3 | } 4 | 5 | datatype Interface = 6 | int(inf: Map, 7 | fm: Map>, 8 | FP: Set, 9 | FPo: Set); 10 | 11 | procedure test_model(x: Node, Ix: Interface, y: Node) 12 | requires Ix.FP == {x} && Ix.inf[x] == 1 && Ix.FPo == {y} && Ix.fm[x][y] == 1 13 | requires forall I: Interface, n: Node, n1: Node :: (n !in I.FP ==> I.inf[n] == 0 && I.fm[n][n1] == 0) && (n1 !in I.FPo ==> I.fm[n][n1] == 0) 14 | ensures forall n in Ix.FPo :: Ix.fm[x][n] == 0 15 | {} 16 | -------------------------------------------------------------------------------- /tests/spl/adt/pairs.spl: -------------------------------------------------------------------------------- 1 | datatype Pair = pair(fst: Int, snd: Int); 2 | 3 | procedure test(p: Pair) 4 | requires p == pair(5, 2) 5 | ensures p.fst == 5 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /tests/spl/array/bsearch.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | // TODO: run quicksort_distinct on skolem 4 | // heap access is also not being checked inside formulas! 5 | 6 | // Find the 1st element in given (nonempty) range [begin, end) that is not less than x. If no such element exists then returns end. 7 | procedure lower_bound(a: Array, x: Int, begin: Int, end: Int) returns (idx: Int) 8 | requires array(a) 9 | requires forall i: Int, j: Int :: begin <= i && i < j && j < end ==> a[i] <= a[j] 10 | requires 0 <= begin && begin < end && end <= a.length 11 | ensures array(a) 12 | ensures begin <= idx && (idx < end && a[idx] >= x && (idx > begin ==> a[idx-1] < x)) || (idx == end && a[idx-1] < x) 13 | { 14 | var lo := begin; 15 | var hi := end; 16 | 17 | while (hi > lo) 18 | invariant array(a) 19 | invariant forall i: Int, j: Int :: begin <= i && i < j && j < end ==> a[i] <= a[j] 20 | invariant begin <= lo && lo <= hi && hi <= end 21 | invariant (lo < end && (a[lo] < x || (a[lo] >= x && (lo > begin ==> a[lo-1] < x)))) || (lo == end && a[lo-1] < x) 22 | invariant hi == end || a[hi] >= x 23 | { 24 | var mid := (lo + hi) / 2; 25 | if (a[mid] < x) { 26 | lo := mid + 1; 27 | } else { 28 | hi := mid; 29 | } 30 | } 31 | idx := lo; 32 | } 33 | -------------------------------------------------------------------------------- /tests/spl/array/bubble.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | 4 | /* One pass of bubble sort should leave the maximum element in the correct position */ 5 | procedure bubble_one_pass(a: Array, high: Int, ghost lb: Int, ghost ub: Int) 6 | requires acc(a) &*& arrayseg_bnd(a, 0, high, lb, ub) 7 | requires high >= 0 && high <= a.length 8 | ensures acc(a) &*& arrayseg_bnd(a, 0, high, lb, ub) 9 | ensures forall j: Int :: 0 <= j && j < high ==> a[j] <= a[high-1] 10 | { 11 | if (high == 0 || high == 1) 12 | { 13 | return; 14 | } 15 | var i := 1; 16 | 17 | while (i < high) 18 | invariant 1 <= i && i <= high && high <= a.length 19 | invariant acc(a) &*& arrayseg_bnd(a, 0, high, lb, ub) 20 | invariant forall j: Int :: 0 <= j && j < i ==> a[j] <= a[i-1] 21 | { 22 | if (a[i] < a[i - 1]) 23 | { 24 | var x := a[i]; 25 | a[i] := a[i - 1]; 26 | a[i - 1] := x; 27 | } 28 | i := i + 1; 29 | } 30 | } 31 | 32 | 33 | procedure bubble_sort(a: Array, implicit ghost lb: Int, implicit ghost ub: Int) 34 | requires array_bnd(a, lb, ub) 35 | ensures sorted_array_bnd(a, lb, ub) 36 | { 37 | var high := a.length; 38 | 39 | while (high > 0) 40 | invariant acc(a) 41 | invariant (high == a.length &*& arrayseg_bnd(a, 0, high, lb, ub)) || 42 | (high < a.length &*& a[high] >= lb &*& arrayseg_bnd(a, 0, high, lb, a[high]+1)) 43 | invariant sorted_arrayseg_bnd(a, high, a.length, a[high], ub) 44 | invariant 0 <= high && high <= a.length 45 | { 46 | if (high == a.length) 47 | { 48 | bubble_one_pass(a, high, lb, ub); 49 | } 50 | else 51 | { 52 | bubble_one_pass(a, high, lb, a[high]+1); 53 | } 54 | high := high - 1; 55 | } 56 | return; 57 | } 58 | -------------------------------------------------------------------------------- /tests/spl/array/checkSorted.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure chechSorted(a: Array, implicit ghost content: Set) 4 | requires sorted_array(a, content) 5 | ensures sorted_array(a, content) 6 | { 7 | var i := 0; 8 | 9 | while (i < a.length - 1) 10 | invariant 0 <= i && i <= a.length 11 | invariant sorted_array(a, content) 12 | { 13 | pure assert(a[i] <= a[i+1]); 14 | i := i + 1; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/spl/array/clamp.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | // @author David Stingley and Jenny Ramseyer 4 | 5 | procedure clamp(a: Array, bLower: Int, bUpper: Int) 6 | requires array(a) 7 | requires bLower <= bUpper 8 | ensures array(a) 9 | ensures forall i: Int:: i >= 0 && i < a.length ==> a[i] <= bUpper && a[i] >= bLower 10 | { 11 | var i := 0; 12 | 13 | while(i < a.length) 14 | invariant i >= 0 && i <= a.length 15 | invariant bLower <= bUpper 16 | invariant array(a) 17 | invariant forall j: Int:: j >= 0 && j < i ==> a[j] <= bUpper && a[j] >= bLower 18 | { 19 | if(a[i] < bLower){ 20 | a[i] := bLower; 21 | } else if(a[i] > bUpper){ 22 | a[i] := bUpper; 23 | } 24 | i := i + 1; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/array/copy.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure copy(a: Array) 4 | returns (b: Array) 5 | requires array(a) 6 | ensures array(a) &*& array(b) 7 | ensures a.length == b.length 8 | ensures forall i: Int :: 0 <= i && i < a.length ==> a[i] == b[i] 9 | { 10 | b := new Array(a.length); 11 | 12 | var i := 0; 13 | 14 | while (i < a.length) 15 | invariant 0 <= i && i <= a.length && a.length == b.length 16 | invariant array(a) &*& array(b) 17 | invariant forall j: Int :: 0 <= j && j < i ==> a[j] == b[j] 18 | { 19 | b[i] := a[i]; 20 | i := i + 1; 21 | } 22 | 23 | return b; 24 | } 25 | -------------------------------------------------------------------------------- /tests/spl/array/copyByte.spl: -------------------------------------------------------------------------------- 1 | include "../include/byte_array.spl"; 2 | 3 | procedure copyByte(a: Array) 4 | returns (b: Array) 5 | requires byte_array(a) 6 | ensures byte_array(a) &*& byte_array(b) 7 | ensures a.length == b.length 8 | ensures forall i: Int:: i >= 0 && i < a.length ==> a[i] == b[i] 9 | { 10 | b := new Array(a.length); 11 | 12 | var i := 0; 13 | 14 | while (i < a.length) 15 | invariant i >= 0 && i <= a.length && a.length == b.length 16 | invariant byte_array(a) &*& byte_array(b) 17 | invariant forall j: Int:: j >= 0 && j < i ==> a[j] == b[j] 18 | { 19 | b[i] := a[i]; 20 | i := i + 1; 21 | } 22 | 23 | return b; 24 | } 25 | -------------------------------------------------------------------------------- /tests/spl/array/copy_byte_slice.spl: -------------------------------------------------------------------------------- 1 | include "../include/byte_array.spl"; 2 | 3 | 4 | procedure copy_byte_slice(a: Array, start: Int, end: Int) 5 | returns (b: Array) 6 | requires byte_array(a) 7 | requires start >= 0 8 | requires end > 0 9 | requires end <= a.length 10 | requires start < a.length 11 | requires end > start 12 | ensures byte_array(a) &*& byte_array(b) 13 | ensures a.length >= b.length 14 | ensures b.length == end - start 15 | ensures forall i: Int:: i >= 0 && i < (end-start) ==> b[i] == a[i+start] 16 | { 17 | var finalLength := end - start; 18 | b := new Array(finalLength); 19 | 20 | var i := 0; 21 | 22 | while (i < finalLength) 23 | invariant byte_array(a) &*& byte_array(b) 24 | invariant i >= 0 && i <= finalLength 25 | invariant finalLength == end - start 26 | invariant end > start 27 | invariant start >= 0 28 | invariant end <= a.length 29 | invariant b.length == finalLength 30 | invariant forall j: Int:: j >= 0 && j < i ==> a[j+start] == b[j] 31 | { 32 | b[i] := a[i+start]; 33 | i := i + 1; 34 | } 35 | 36 | return b; 37 | } 38 | -------------------------------------------------------------------------------- /tests/spl/array/destroy.spl: -------------------------------------------------------------------------------- 1 | include "../include/node_array.spl"; 2 | 3 | struct Node { 4 | var data: Int; 5 | } 6 | 7 | procedure destroy(a: Array, implicit ghost N: Set) 8 | requires array_with_content(a, N) &*& acc(N) 9 | ensures emp 10 | { 11 | var i := 0; 12 | while (i < a.length) 13 | invariant 0 <= i && i <= a.length 14 | invariant 15 | exists N2: Set :: 16 | (arrayseg_with_content(a, i, a.length, N2) -** array(a)) &*& acc(N2) 17 | { 18 | free a[i]; 19 | i := i + 1; 20 | } 21 | free a; 22 | } 23 | -------------------------------------------------------------------------------- /tests/spl/array/free.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure free_array(a: Array) 4 | requires array(a) 5 | ensures emp 6 | { 7 | free a; 8 | } 9 | -------------------------------------------------------------------------------- /tests/spl/array/initialize.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure initialize() 4 | returns (a: Array) 5 | requires emp 6 | ensures array(a) 7 | ensures forall k: Int :: 0 <= k && k < a.length ==> a[k] == k 8 | { 9 | a := new Array(10); 10 | 11 | var i := 0; 12 | 13 | while (i < a.length) 14 | invariant i >= 0 15 | invariant array(a) 16 | invariant forall k: Int :: 0 <= k && k < i ==> a[k] == k 17 | { 18 | a[i] := i; 19 | i := i + 1;} 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/array/maximum.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure maximum(a: Array) 4 | returns (max_i: Int) 5 | requires array(a) 6 | ensures array(a) 7 | ensures a.length == 0 || (0 <= max_i && max_i < a.length) 8 | ensures forall j: Int :: 0 <= j && j < a.length ==> a[j] <= a[max_i] 9 | { 10 | var i := 0; 11 | max_i := 0; 12 | 13 | while (i < a.length) 14 | invariant 0 <= i 15 | invariant array(a) 16 | invariant forall j: Int :: 0 <= j && j < i ==> a[j] <= a[max_i] 17 | invariant a.length == 0 || (0 <= max_i && max_i < a.length) 18 | { 19 | if (a[i] > a[max_i]) 20 | { 21 | max_i := i; 22 | } 23 | i := i + 1; 24 | } 25 | return max_i; 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/array/quicksort.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure quicksort(a: Array, implicit ghost content: Set) 4 | requires array_cnt(a, content) 5 | ensures sorted_array(a, content) 6 | { 7 | quicksort1(a, 0, a.length-1, content); 8 | } 9 | 10 | procedure swap(a: Array, i: Int, j: Int, implicit ghost iVal: Int, implicit ghost jVal: Int) 11 | requires acc(a) &*& (acc(a,i) &+& acc(a, j)) &*& a[i] == iVal &*& a[j] == jVal 12 | ensures acc(a) &*& (acc(a,i) &+& acc(a, j)) &*& a[i] == jVal &*& a[j] == iVal 13 | { 14 | var tmp := a[i]; 15 | a[i] := a[j]; 16 | a[j] := tmp; 17 | } 18 | 19 | procedure quicksort1(a: Array, lower: Int, upper: Int, ghost content: Set) 20 | requires acc(a) &*& arrayseg_cnt(a, lower, upper+1, content) 21 | ensures acc(a) &*& sorted_arrayseg(a, lower, upper+1, content) 22 | { 23 | if (lower < upper) { 24 | var pivotIdx := lower + (upper - lower) / 2; 25 | var pivotVal := a[pivotIdx]; 26 | swap(a, pivotIdx, upper); 27 | var idx := lower; 28 | var i := lower; 29 | ghost var C1 := Set(); 30 | ghost var C2 := Set(); 31 | //var C3 := content -- Set(a[upper]); //only true for multiset 32 | ghost var C3: Set; 33 | pure assume(C3 == content || C3 == content -- Set(a[upper])); 34 | while (i < upper) 35 | invariant idx >= lower && i <= upper && i >= idx 36 | invariant acc(a) &*& acc(a, upper) 37 | invariant arrayseg_cnt(a, lower, idx, C1) 38 | invariant arrayseg_cnt(a, idx, i, C2) 39 | invariant arrayseg_cnt(a, i, upper, C3) 40 | invariant content == C1 ++ C2 ++ C3 ++ Set(a[upper]) 41 | invariant forall k in C1:: k < pivotVal 42 | invariant forall k in C2:: k >= pivotVal 43 | { 44 | if (a[i] < pivotVal) { 45 | swap(a, i, idx); 46 | idx := idx + 1; 47 | C1 := C1 ++ Set(a[i]); 48 | } else { 49 | C2 := C2 ++ Set(a[i]); 50 | } 51 | //C3 := C3 -- Set(a[i]); //only true for multiset! 52 | ghost var tmp := C3; 53 | havoc(C3); 54 | pure assume(C3 == tmp || C3 == tmp -- Set(a[i])); 55 | // 56 | i := i + 1; 57 | } 58 | swap(a, idx, upper); 59 | quicksort1(a, lower, idx - 1, C1); 60 | quicksort1(a, idx + 1, upper, C2); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /tests/spl/array/quicksort_bound_only.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure quicksort(a: Array, implicit ghost lb: Int, implicit ghost ub: Int) 4 | requires array_bnd(a, lb, ub) 5 | ensures sorted_array_bnd(a, lb, ub) 6 | { 7 | quicksort1(a, 0, a.length-1, lb, ub); 8 | } 9 | 10 | procedure swap(a: Array, i: Int, j: Int) 11 | requires acc(a) &*& (acc(a, i) &+& acc(a, j)) 12 | ensures acc(a) &*& (acc(a, i) &+& acc(a, j)) &*& a[i] == old(a[j]) &*& a[j] == old(a[i]) 13 | { 14 | var tmp := a[i]; 15 | a[i] := a[j]; 16 | a[j] := tmp; 17 | } 18 | 19 | procedure quicksort1(a: Array, lower: Int, upper: Int, ghost lb: Int, ghost ub: Int) 20 | requires acc(a) &*& arrayseg_bnd(a, lower, upper+1, lb, ub) 21 | ensures acc(a) &*& sorted_arrayseg_bnd(a, lower, upper+1, lb, ub) 22 | { 23 | if (lower < upper) { 24 | var pivotIdx := lower + (upper - lower) / 2; 25 | var pivotVal := a[pivotIdx]; 26 | swap(a, pivotIdx, upper); 27 | var idx := lower; 28 | var i := lower; 29 | while (i < upper) 30 | invariant lower <= idx && idx <= i && i <= upper 31 | invariant acc(a) 32 | invariant arrayseg_bnd(a, lower, idx, lb, pivotVal) 33 | invariant arrayseg_bnd(a, idx, i, pivotVal, ub) 34 | invariant arrayseg_bnd(a, i, upper, lb, ub) 35 | { 36 | if (a[i] < pivotVal) { 37 | swap(a, i, idx); 38 | idx := idx + 1; 39 | } 40 | i := i + 1; 41 | } 42 | swap(a, idx, upper); 43 | quicksort1(a, lower, idx - 1, lb, pivotVal); 44 | quicksort1(a, idx + 1, upper, pivotVal, ub); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/spl/array/quicksort_distinct.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure quicksort(a: Array, implicit ghost content: Set) 4 | requires array_cnt(a, content) 5 | requires forall i: Int, j: Int :: 0 <= i && i < j && j < a.length ==> a[i] != a[j] 6 | ensures sorted_array(a, content) 7 | { 8 | quicksort1(a, 0, a.length-1, content); 9 | } 10 | 11 | procedure swap(a: Array, i: Int, j: Int, implicit ghost iVal: Int, implicit ghost jVal: Int) 12 | requires acc(a) &*& (acc(a,i) &+& acc(a, j)) &*& a[i] == iVal &*& a[j] == jVal 13 | ensures acc(a) &*& (acc(a,i) &+& acc(a, j)) &*& a[i] == jVal &*& a[j] == iVal 14 | { 15 | var tmp := a[i]; 16 | a[i] := a[j]; 17 | a[j] := tmp; 18 | } 19 | 20 | procedure quicksort1(a: Array, lower: Int, upper: Int, ghost content: Set) 21 | requires acc(a) &*& arrayseg_cnt(a, lower, upper+1, content) 22 | requires forall i: Int, j: Int :: 0 <= i && i < j && j < a.length ==> a[i] != a[j] 23 | ensures acc(a) &*& sorted_arrayseg(a, lower, upper+1, content) 24 | { 25 | if (lower < upper) { 26 | var pivotIdx := lower + (upper - lower) / 2; 27 | var pivotVal := a[pivotIdx]; 28 | swap(a, pivotIdx, upper); 29 | var idx := lower; 30 | var i := lower; 31 | var C1 := Set(); 32 | var C2 := Set(); 33 | var C3 := content -- Set(a[upper]); // distinct so this is ok 34 | while (i < upper) 35 | invariant idx >= lower && i <= upper && i >= idx 36 | invariant acc(a) &*& acc(a, upper) 37 | invariant forall k: Int, j: Int :: 0 <= k && k < j && j < a.length ==> a[k] != a[j] 38 | invariant arrayseg_cnt(a, lower, idx, C1) 39 | invariant arrayseg_cnt(a, idx, i, C2) 40 | invariant arrayseg_cnt(a, i, upper, C3) 41 | invariant content == C1 ++ C2 ++ C3 ++ Set(a[upper]) 42 | invariant forall k in C1:: k < pivotVal 43 | invariant forall k in C2:: k >= pivotVal 44 | { 45 | if (a[i] < pivotVal) { 46 | swap(a, i, idx); 47 | idx := idx + 1; 48 | C1 := C1 ++ Set(a[i]); 49 | } else { 50 | C2 := C2 ++ Set(a[i]); 51 | } 52 | C3 := C3 -- Set(a[i]); // distinct so ok. 53 | i := i + 1; 54 | } 55 | swap(a, idx, upper); 56 | quicksort1(a, lower, idx - 1, C1); 57 | quicksort1(a, idx + 1, upper, C2); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tests/spl/array/reverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | // This procedure works 4 | procedure copy_reverse(a: Array) 5 | returns (b: Array) 6 | requires array(a) 7 | ensures array(a) &*& array(b) 8 | ensures a.length == b.length 9 | ensures forall j: Int:: j >= 0 && j < b.length ==> b[j] == a[a.length - 1 - j] 10 | { 11 | b := new Array(a.length); 12 | 13 | var i := 0; 14 | 15 | while (i < b.length) 16 | invariant i >= 0 && i <= b.length && a.length == b.length 17 | invariant array(a) &*& array(b) 18 | invariant forall j: Int:: j >= 0 && j < i ==> b[j] == a[a.length - 1 - j] 19 | { 20 | b[i] := a[a.length - 1 - i]; 21 | i := i + 1; 22 | } 23 | 24 | return b; 25 | } 26 | 27 | // TODO but for some strange reason this doesn't!? 28 | /* 29 | procedure copy_reverse1(a: Array) 30 | returns (b: Array) 31 | requires array(a) 32 | ensures array(a) &*& array(b) 33 | ensures a.length == b.length 34 | ensures forall j: Int:: j >= 0 && j < a.length ==> a[j] == b[a.length - j - 1] 35 | { 36 | b := new Array(a.length); 37 | 38 | var i := 0; 39 | 40 | while (i < a.length) 41 | invariant i >= 0 && i <= a.length && a.length == b.length 42 | invariant array(a) &*& array(b) 43 | invariant forall j: Int:: j >= 0 && j < i ==> a[j] == b[a.length - 1 - j] 44 | { 45 | b[a.length - 1 - i] := a[i]; 46 | i := i + 1; 47 | } 48 | 49 | return b; 50 | } 51 | */ 52 | -------------------------------------------------------------------------------- /tests/spl/array/selection_sort.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure find_minimum(a: Array, low: Int, high: Int) 4 | returns (min_i: Int) 5 | requires array(a) 6 | requires 0 <= low && low <= high && high <= a.length 7 | ensures array(a) 8 | ensures low == high || (low <= min_i && min_i < high) 9 | ensures forall j: Int :: low <= j && j < high ==> a[j] >= a[min_i] 10 | { 11 | var i := low; 12 | min_i := low; 13 | 14 | while (i < high) 15 | invariant low <= i 16 | invariant forall j: Int :: low <= j && j < i ==> a[j] >= a[min_i] 17 | invariant low == high || (low <= min_i && min_i < high) 18 | { 19 | if (a[i] < a[min_i]) 20 | { 21 | min_i := i; 22 | } 23 | i := i + 1; 24 | } 25 | return min_i; 26 | } 27 | 28 | 29 | procedure selection_sort(a: Array, implicit ghost content: Set) 30 | requires array(a) 31 | ensures array(a) 32 | ensures forall j: Int, k: Int :: 0 <= j && j <= k && k < a.length ==> a[j] <= a[k] 33 | { 34 | var i := 0; 35 | 36 | while (i < a.length) 37 | invariant 0 <= i && i <= a.length 38 | invariant array(a) 39 | invariant forall j: Int, k: Int :: 0 <= j && j < i && j <= k && k < a.length ==> a[j] <= a[k] 40 | { 41 | var min_i := find_minimum(a, i, a.length); 42 | var temp := a[i]; 43 | a[i] := a[min_i]; 44 | a[min_i] := temp; 45 | 46 | i := i + 1; 47 | } 48 | return; 49 | } 50 | -------------------------------------------------------------------------------- /tests/spl/array/test.spl: -------------------------------------------------------------------------------- 1 | include "../include/int_array.spl"; 2 | 3 | procedure heap_access_conditional(a: Array, x: Int, begin: Int, end: Int) returns (idx: Int) 4 | requires array(a) 5 | requires begin < end 6 | ensures array(a) 7 | { 8 | var lo := begin; 9 | 10 | while (lo < end) 11 | invariant true 12 | { 13 | // This causes an error, but the if condition doesn't! 14 | // var b := a[lo]; 15 | if (a[lo] < x) 16 | { 17 | lo := lo + 1; 18 | } 19 | } 20 | idx := lo; 21 | } 22 | 23 | procedure unsat_precondition(a: Array) returns (y: Int) 24 | requires acc(a) &*& acc(a) 25 | ensures y == 3 26 | { 27 | y := 2; 28 | } 29 | 30 | procedure test_invariant_bug(a: Array, high: Int) 31 | requires acc(a) &*& arrayseg(a, 0, high) 32 | requires high >= 0 && high <= a.length 33 | ensures acc(a) &*& arrayseg(a, 0, high) 34 | { 35 | var i := 0; 36 | 37 | while (i < high) 38 | invariant 0 <= i && i <= high 39 | invariant acc(a) &*& arrayseg(a, 0, high) 40 | invariant forall j: Int :: 0 <= j && j < i ==> a[j] == 4 41 | { 42 | a[i] := 4; 43 | 44 | i := i + 1; 45 | } 46 | } 47 | 48 | /* 49 | procedure test_heap_access(a: Array, high: Int) 50 | requires acc(a) &*& arrayseg(a, 0, high) 51 | requires high >= 0 && high <= a.length 52 | ensures acc(a) &*& arrayseg(a, 0, high) 53 | { 54 | var i := 0; 55 | 56 | while (i < high) 57 | invariant 0 <= i && i <= high && high <= a.length 58 | invariant acc(a) &*& arrayseg(a, 0, high) 59 | { 60 | a[i] := a[i]; 61 | i := i + 1; 62 | } 63 | 64 | } 65 | 66 | 67 | 68 | procedure create() 69 | returns (a: Array) 70 | requires emp 71 | ensures array(a) &*& a[0] == 111 72 | { 73 | a := new Array(1); 74 | 75 | a[0] := 111; 76 | 77 | var b:= new Array(2); 78 | b[0] := 555; 79 | b[1] := 666; 80 | 81 | return a; 82 | } 83 | */ 84 | -------------------------------------------------------------------------------- /tests/spl/array/traverse_with_nodes.spl: -------------------------------------------------------------------------------- 1 | include "../include/node_array.spl"; 2 | 3 | struct Node { 4 | var data: Int; 5 | } 6 | 7 | procedure traverse(a: Array) 8 | requires array(a) 9 | ensures array(a) 10 | { 11 | var i := 0; 12 | 13 | while (i < a.length) 14 | invariant 0 <= i 15 | invariant array(a) 16 | { 17 | a[i] := a[i]; 18 | i := i + 1; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/assoc/contains.spl: -------------------------------------------------------------------------------- 1 | include "../include/assoc_list.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure contains(lst: Node, val: Int, implicit ghost C: Set, implicit ghost D: Map) 6 | returns (res: Bool) 7 | requires list_map(lst, null, C, D) 8 | ensures (res == val in C) &*& list_map(lst, null, C, D) 9 | { 10 | var curr: Node; 11 | curr := lst; 12 | var prev: Node; 13 | prev := null; 14 | while (curr != null && curr.key < val) 15 | invariant (prev == null && curr == lst || val > prev.key &*& prev.next |-> curr) -** 16 | list_map(lst, null, C, D) 17 | { 18 | prev := curr; 19 | curr := curr.next; 20 | } 21 | if (curr != null && curr.key == val) return true; 22 | else return false; 23 | } 24 | -------------------------------------------------------------------------------- /tests/spl/assoc/insert.spl: -------------------------------------------------------------------------------- 1 | include "../include/assoc_list.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure insert(lst: Node, k: Int, v: Int, 6 | implicit ghost C: Set, 7 | implicit ghost D1: Map, 8 | implicit ghost D2: Map) 9 | returns (res: Node) 10 | requires list_map(lst, null, C, D1) 11 | requires (forall x in C :: (x != k ==> x.D2 == x.D1) @(matching x.D2 yields x.D1) @(matching x.D1 yields x.D2)) 12 | requires k.D2 == v 13 | ensures list_map(res, null, C ++ Set(k), D2) 14 | { 15 | var curr: Node; 16 | curr := lst; 17 | var prev: Node; 18 | prev := null; 19 | while (curr != null && curr.key < k) 20 | invariant (prev == null && curr == lst || k > prev.key &*& prev.next |-> curr) -** 21 | list_map(lst, null, C, D1) 22 | { 23 | prev := curr; 24 | curr := curr.next; 25 | } 26 | if (curr != null && curr.key == k) { 27 | curr.data := v; 28 | return lst; 29 | } 30 | 31 | var n := new Node; 32 | n.next := curr; 33 | n.key := k; 34 | n.data := v; 35 | if (prev == null) { 36 | return n; 37 | } else { 38 | prev.next := n; 39 | return lst; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/spl/assoc/lookup.spl: -------------------------------------------------------------------------------- 1 | include "../include/assoc_list.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure lookup(lst: Node, val: Int, implicit ghost C: Set, implicit ghost D: Map) 6 | returns (res: Int) 7 | requires list_map(lst, null, C, D) &*& val in C 8 | ensures (res == val.D) &*& list_map(lst, null, C, D) 9 | { 10 | var curr: Node; 11 | curr := lst; 12 | var prev: Node; 13 | prev := null; 14 | while (curr.key < val) 15 | invariant 16 | (prev == null && curr == lst || val > prev.key &*& prev.next |-> curr) -** 17 | list_map(lst, null, C, D) &*& val in C 18 | { 19 | prev := curr; 20 | curr := curr.next; 21 | } 22 | return curr.data; 23 | } 24 | 25 | procedure lookupOpt(lst: Node, val: Int, implicit ghost C: Set, implicit ghost D: Map) 26 | returns (res: Int) 27 | requires list_map(lst, null, C, D) 28 | ensures list_map(lst, null, C, D) 29 | ensures (val in C && res == val.D) || (!(val in C) && res == -1) 30 | { 31 | var curr: Node; 32 | curr := lst; 33 | var prev: Node; 34 | prev := null; 35 | while (curr != null && curr.key < val) 36 | invariant (prev == null && curr == lst || val > prev.key &*& prev.next |-> curr) -** 37 | list_map(lst, null, C, D) 38 | { 39 | prev := curr; 40 | curr := curr.next; 41 | } 42 | if (curr != null && curr.key == val) return curr.data; 43 | else return -1; 44 | } 45 | -------------------------------------------------------------------------------- /tests/spl/assoc/remove.spl: -------------------------------------------------------------------------------- 1 | include "../include/assoc_list.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure remove(lst: Node, k: Int, 6 | implicit ghost C: Set, 7 | implicit ghost D1: Map, 8 | implicit ghost D2: Map) 9 | returns (res: Node) 10 | requires list_map(lst, null, C, D1) 11 | requires (forall x in C :: (x != k ==> x.D2 == x.D1) @(matching x.D2 yields x.D1) @(matching x.D1 yields x.D2)) 12 | ensures list_map(res, null, C -- Set(k), D2) 13 | { 14 | var curr: Node; 15 | curr := lst; 16 | var prev: Node; 17 | prev := null; 18 | while (curr != null && curr.key < k) 19 | invariant (prev == null && curr == lst || k > prev.key &*& prev.next |-> curr) -** 20 | list_map(lst, null, C, D1) 21 | { 22 | prev := curr; 23 | curr := curr.next; 24 | } 25 | if (curr != null && curr.key == k) { 26 | var n: Node; 27 | n := curr; 28 | curr := curr.next; 29 | free n; 30 | if (prev != null) { 31 | prev.next := curr; 32 | return lst; 33 | } else { 34 | return curr; 35 | } 36 | } else { 37 | return lst; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/spl/bitvector/arithmetic.spl: -------------------------------------------------------------------------------- 1 | include "../array/byte_array.spl"; 2 | 3 | procedure Main(arg: Array) returns (res: Int) 4 | requires byte_array(arg) 5 | ensures emp 6 | { 7 | free(arg); 8 | var a := 23; 9 | var b := a + 1; 10 | pure assert b == 24; 11 | var c := (1024 + 23) & 0xFF; 12 | pure assert c == 23; 13 | var d := int2byte(c); 14 | pure assert d == int2byte(23); 15 | pure assert d >= int2byte(23); 16 | pure assert d <= int2byte(23); 17 | pure assert c == byte2int(d); 18 | var e := d & int2byte(0xF); 19 | pure assert e == int2byte(7); 20 | var f := d + e; 21 | pure assert f == int2byte(30); 22 | pure assert int2byte(4)*f == int2byte(30) <-< 1 <-< 1; 23 | pure assert int2byte(4)*f == int2byte(30) <-< 2 ; 24 | pure assert int2byte(48) == '0'; 25 | return 0; 26 | } 27 | 28 | procedure ultTest() 29 | { 30 | pure assert -1 > -2; 31 | pure assert -1 < 0; 32 | pure assert 1 > 0; 33 | pure assert 1 > -1; 34 | pure assert 2 > 1; 35 | pure assert int2byte(-1) > int2byte(-2); 36 | pure assert int2byte(-1) < int2byte( 0); 37 | pure assert int2byte( 1) > int2byte( 0); 38 | pure assert int2byte( 1) > int2byte(-1); 39 | pure assert int2byte( 2) > int2byte( 1); 40 | } 41 | -------------------------------------------------------------------------------- /tests/spl/bitvector/intToByteArray.spl: -------------------------------------------------------------------------------- 1 | include "../array/byte_array.spl"; 2 | 3 | procedure intToByteArray(i: Int) returns (arr: Array) 4 | requires emp 5 | ensures byte_array(arr) &*& arr.length == 4 6 | { 7 | arr := new Array(4); 8 | arr[0] := int2byte(i >-> 0); 9 | arr[1] := int2byte(i >-> 8); 10 | arr[2] := int2byte(i >-> 16); 11 | arr[3] := int2byte(i >-> 24); 12 | return arr; 13 | } 14 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/int_array.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | 21 | /* 22 | * Main Function, here for compilability 23 | */ 24 | int main() { 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/proc0.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | 21 | /* 22 | * Procedures 23 | */ 24 | void proc1_1 (); 25 | void proc2_1 (int a_6); 26 | void proc3_1 (int a_7, int b_3); 27 | int proc4_1 (); 28 | int proc5_1 (int a_8); 29 | int proc6_1 (int a_9, int b_4); 30 | void proc7_1 (int* ar_16, int* br_6); 31 | void proc8_1 (int a_10, int* ar_17, int* br_7); 32 | void proc9_1 (int a_11, int b_5, int* ar_18, int* br_8); 33 | 34 | void proc1_1 () { 35 | 36 | } 37 | 38 | void proc2_1 (int a_6) { 39 | 40 | } 41 | 42 | void proc3_1 (int a_7, int b_3) { 43 | 44 | } 45 | 46 | int proc4_1 () { 47 | int ar_13; 48 | ar_13 = 4; 49 | return ar_13; 50 | } 51 | 52 | int proc5_1 (int a_8) { 53 | int ar_14; 54 | ar_14 = a_8; 55 | return ar_14; 56 | } 57 | 58 | int proc6_1 (int a_9, int b_4) { 59 | int ar_15; 60 | ar_15 = a_9; 61 | ar_15 = b_4; 62 | return ar_15; 63 | } 64 | 65 | void proc7_1 (int* ar_16, int* br_6) { 66 | (*ar_16) = 4; 67 | (*br_6) = 5; 68 | } 69 | 70 | void proc8_1 (int a_10, int* ar_17, int* br_7) { 71 | (*ar_17) = a_10; 72 | (*br_7) = 5; 73 | } 74 | 75 | void proc9_1 (int a_11, int b_5, int* ar_18, int* br_8) { 76 | (*ar_18) = a_11; 77 | (*br_8) = b_5; 78 | } 79 | 80 | /* 81 | * Main Function, here for compilability 82 | */ 83 | int main() { 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/proc0.spl: -------------------------------------------------------------------------------- 1 | procedure proc1() 2 | returns () 3 | { 4 | } 5 | 6 | procedure proc2(a: Int) 7 | returns () 8 | { 9 | } 10 | 11 | procedure proc3(a: Int, b: Int) 12 | returns () 13 | { 14 | } 15 | 16 | procedure proc4() 17 | returns (ar: Int) 18 | { 19 | ar := 4; 20 | } 21 | 22 | procedure proc5(a: Int) 23 | returns (ar: Int) 24 | { 25 | ar := a; 26 | } 27 | 28 | procedure proc6(a: Int, b: Int) 29 | returns (ar: Int) 30 | { 31 | ar := a; 32 | ar := b; 33 | } 34 | 35 | procedure proc7() 36 | returns (ar: Int, br: Int) 37 | { 38 | ar := 4; 39 | br := 5; 40 | } 41 | 42 | procedure proc8(a: Int) 43 | returns (ar: Int, br: Int) 44 | { 45 | ar := a; 46 | br := 5; 47 | } 48 | 49 | procedure proc9(a: Int, b: Int) 50 | returns (ar: Int, br: Int) 51 | { 52 | ar := a; 53 | br := b; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/proc1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | 21 | /* 22 | * Procedures 23 | */ 24 | int proc0_1 (int a_3); 25 | int proc1_1 (int a_4); 26 | int proc2_1 (int a_5); 27 | 28 | int proc0_1 (int a_3) { 29 | int b_12; 30 | int tmp_2; 31 | 32 | if ((a_3 == 0)) { 33 | b_12 = 0; 34 | } else { 35 | tmp_2 = proc0_1((a_3 - 1)); 36 | b_12 = (a_3 + tmp_2); 37 | } 38 | return b_12; 39 | } 40 | 41 | int proc1_1 (int a_4) { 42 | int b_13; 43 | if ((a_4 == 0)) { 44 | return 0; 45 | } else { 46 | b_13 = proc2_1(a_4); 47 | return b_13; 48 | } 49 | return b_13; 50 | } 51 | 52 | int proc2_1 (int a_5) { 53 | int b_14; 54 | if ((a_5 < 0)) { 55 | b_14 = proc1_1((a_5 + 1)); 56 | return b_14; 57 | } else { 58 | b_14 = proc1_1((a_5 - 1)); 59 | return b_14; 60 | } 61 | return b_14; 62 | } 63 | 64 | /* 65 | * Main Function, here for compilability 66 | */ 67 | int main() { 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/proc1.spl: -------------------------------------------------------------------------------- 1 | procedure proc0 (a: Int) 2 | returns (b: Int) 3 | { 4 | if (a == 0) 5 | { 6 | b := 0; 7 | } 8 | else 9 | { 10 | b := a + proc0(a-1); 11 | } 12 | } 13 | 14 | procedure proc1 (a: Int) 15 | returns (b: Int) 16 | { 17 | if (a == 0) 18 | { 19 | return 0; 20 | } else 21 | { 22 | return proc2(a); 23 | } 24 | } 25 | 26 | procedure proc2 (a: Int) 27 | returns (b: Int) 28 | { 29 | if (a < 0) 30 | { 31 | return proc1(a+1); 32 | } else 33 | { 34 | return proc1(a-1); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/proc2.spl: -------------------------------------------------------------------------------- 1 | include "int_array.spl"; 2 | 3 | // This takes care of the Read, Length and New expressions. 4 | // I tried to develop my own procedure to test them, but GRASShopper 5 | // would never finish computing their correctness. 6 | procedure copy(a: Array) 7 | returns (b: Array) 8 | requires array(a) 9 | ensures array(a) &*& array(b) 10 | ensures a.length == b.length 11 | ensures forall i: Int:: i >= 0 && i < a.length ==> a[i] == b[i] 12 | { 13 | b := new Array(a.length); 14 | 15 | var i := 0; 16 | 17 | while (i < a.length) 18 | invariant i >= 0 && i <= a.length && a.length == b.length 19 | invariant array(a) &*& array(b) 20 | invariant forall j: Int:: j >= 0 && j < i ==> a[j] == b[j] 21 | { 22 | b[i] := a[i]; 23 | i := i + 1; 24 | } 25 | 26 | return b; 27 | } 28 | 29 | procedure procNull () 30 | returns (a: Int) 31 | { 32 | if (null == null) 33 | { 34 | a := 1; 35 | } 36 | else 37 | { 38 | a := 0; 39 | } 40 | } 41 | 42 | procedure procIntAndBoolVal () 43 | returns (a: Int, b: Bool) 44 | { 45 | a := 1; 46 | a := -1; 47 | a := 0; 48 | a := 277; 49 | 50 | b := true; 51 | b := false; 52 | } 53 | 54 | procedure procReadLengthNew () 55 | returns (a: Array) 56 | { 57 | a := new Array(10); 58 | var b := a.length; 59 | a[0] := 1; 60 | var c := a[0]; 61 | } 62 | 63 | procedure procCall () 64 | returns (a: Int, b: Bool) 65 | { 66 | return procIntAndBoolVal(); 67 | } 68 | 69 | procedure procOps (a: Int, b: Int, c: Bool, d: Bool) 70 | returns (ap: Int, bp: Int, cp: Bool, dp: Bool) 71 | { 72 | ap := a; 73 | bp := b; 74 | cp := c; 75 | dp := d; 76 | 77 | ap := -ap; 78 | if (!dp) {} 79 | 80 | ap := ap + bp; 81 | bp := ap - bp; 82 | ap := ap * bp; 83 | ap := ap / bp; 84 | if (ap == bp) {} 85 | if (ap > bp) {} 86 | if (ap < bp) {} 87 | if (ap >= bp) {} 88 | if (ap <= bp) {} 89 | if (ap != bp) {} 90 | if (cp && dp) {} 91 | if (cp || dp) {} 92 | if (cp ==> dp) {} 93 | } 94 | 95 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/proc3.spl: -------------------------------------------------------------------------------- 1 | // Test for stmt compilation. 2 | 3 | procedure procBlock () 4 | returns (a: Int, b: Bool, c: Int) 5 | { 6 | a := 1; 7 | a := 2; 8 | a := 3; 9 | 10 | b := false; 11 | c := -2000; 12 | } 13 | 14 | struct SillyStruct { 15 | var a: Int; 16 | } 17 | 18 | procedure procAssign() 19 | { 20 | var a := new SillyStruct(); 21 | var b := new Array(10); 22 | 23 | var x: Int; 24 | var y: Bool; 25 | var z: Int; 26 | x, y, z := procBlock(); 27 | 28 | x, y, z := 1+1, true, (700 * 6)/2; 29 | 30 | x := 100; 31 | } 32 | 33 | procedure procNewArray () 34 | returns (a: Array) 35 | { 36 | return new Array(10); 37 | } 38 | 39 | struct SuperSillyStruct { 40 | var arr: Array; 41 | } 42 | 43 | procedure procDispose(a: Array, b: SillyStruct) 44 | { 45 | free(a); 46 | free(b); 47 | 48 | free(new Array(5)); 49 | 50 | var c := new SuperSillyStruct(); 51 | c.arr := new Array(10); 52 | free(c.arr); 53 | free(c); 54 | 55 | var d := new Array>(5); 56 | d[0] := new Array(5); 57 | free(d[0]); 58 | free(d); 59 | 60 | free(procNewArray()); 61 | } 62 | 63 | procedure procIf(a: Int, b: Int) 64 | returns (c: Bool) 65 | { 66 | if (a == b) 67 | { 68 | c := true; 69 | } 70 | else 71 | { 72 | c := false; 73 | } 74 | } 75 | 76 | procedure procLoop() 77 | { 78 | var i := 0; 79 | 80 | while (i != 5) 81 | { 82 | i := i + 1; 83 | } 84 | } 85 | 86 | procedure procReturn() 87 | returns (a: Int) 88 | { 89 | return 5; 90 | } 91 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/proc5.spl: -------------------------------------------------------------------------------- 1 | struct Node { 2 | var data: Int; 3 | var next: Node; 4 | } 5 | 6 | procedure arrayOfSquares (n: Int) 7 | returns (a: Array) 8 | { 9 | a := new Array(n); 10 | var i := 0; 11 | 12 | while (i < n) 13 | { 14 | a[i] := (i+1) * (i+1); 15 | i := i + 1; 16 | } 17 | } 18 | 19 | procedure getLessThan(a: Array, n: Int) 20 | returns (b: Array) 21 | { 22 | var isLess := new Array(a.length); 23 | var count := 0; 24 | var i := 0; 25 | 26 | while (i < a.length) 27 | { 28 | if (a[i] < n) 29 | { 30 | isLess[i] := true; 31 | count := count + 1; 32 | } 33 | else 34 | { 35 | isLess[i] := false; 36 | } 37 | 38 | i := i + 1; 39 | } 40 | 41 | b := new Array(count); 42 | i := 0; 43 | var j := 0; 44 | while (i < a.length) 45 | { 46 | if (isLess[i]) 47 | { 48 | b[j] := a[i]; 49 | j := j + 1; 50 | } 51 | 52 | i := i + 1; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct0.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | /* 21 | * Structs 22 | */ 23 | struct SomeFields_1; 24 | 25 | typedef struct SomeFields_1 { 26 | int x_1; 27 | bool y_1; 28 | } SomeFields_1; 29 | 30 | /* 31 | * Main Function, here for compilability 32 | */ 33 | int main() { 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct0.spl: -------------------------------------------------------------------------------- 1 | struct SomeFields { 2 | var x: Int; 3 | var y: Bool; 4 | } 5 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | /* 21 | * Structs 22 | */ 23 | struct SomeFields0_1; 24 | struct SomeFields1_1; 25 | struct SomeFields2_1; 26 | struct SomeFields3_1; 27 | struct SomeFields4_1; 28 | 29 | typedef struct SomeFields0_1 { 30 | int x0_1; 31 | bool y0_1; 32 | } SomeFields0_1; 33 | 34 | typedef struct SomeFields1_1 { 35 | int x1_1; 36 | bool y1_1; 37 | } SomeFields1_1; 38 | 39 | typedef struct SomeFields2_1 { 40 | int x2_1; 41 | bool y2_1; 42 | } SomeFields2_1; 43 | 44 | typedef struct SomeFields3_1 { 45 | int x3_1; 46 | bool y3_1; 47 | } SomeFields3_1; 48 | 49 | typedef struct SomeFields4_1 { 50 | int x4_1; 51 | bool y4_1; 52 | } SomeFields4_1; 53 | 54 | /* 55 | * Main Function, here for compilability 56 | */ 57 | int main() { 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct1.spl: -------------------------------------------------------------------------------- 1 | struct SomeFields0 { 2 | var x0: Int; 3 | var y0: Bool; 4 | } 5 | 6 | struct SomeFields1 { 7 | var x1: Int; 8 | var y1: Bool; 9 | } 10 | 11 | struct SomeFields2 { 12 | var x2: Int; 13 | var y2: Bool; 14 | } 15 | 16 | struct SomeFields3 { 17 | var x3: Int; 18 | var y3: Bool; 19 | } 20 | 21 | struct SomeFields4 { 22 | var x4: Int; 23 | var y4: Bool; 24 | } 25 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | /* 21 | * Structs 22 | */ 23 | struct RecStruct_1; 24 | 25 | typedef struct RecStruct_1 { 26 | int data_1; 27 | struct RecStruct_1* next_1; 28 | } RecStruct_1; 29 | 30 | /* 31 | * Main Function, here for compilability 32 | */ 33 | int main() { 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct2.spl: -------------------------------------------------------------------------------- 1 | struct RecStruct { 2 | var next: RecStruct; 3 | var data: Int; 4 | } 5 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | /* 21 | * Structs 22 | */ 23 | struct First_1; 24 | struct Second_1; 25 | 26 | typedef struct First_1 { 27 | struct Second_1* a_1; 28 | } First_1; 29 | 30 | typedef struct Second_1 { 31 | struct First_1* b_1; 32 | } Second_1; 33 | 34 | /* 35 | * Main Function, here for compilability 36 | */ 37 | int main() { 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct3.spl: -------------------------------------------------------------------------------- 1 | struct First { 2 | var a: Second; 3 | } 4 | 5 | struct Second { 6 | var b: First; 7 | } 8 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | /* 21 | * Structs 22 | */ 23 | struct First_1; 24 | struct Second_1; 25 | struct Third_1; 26 | 27 | typedef struct First_1 { 28 | struct Second_1* a_1; 29 | } First_1; 30 | 31 | typedef struct Second_1 { 32 | struct Third_1* b_1; 33 | } Second_1; 34 | 35 | typedef struct Third_1 { 36 | struct First_1* c_1; 37 | } Third_1; 38 | 39 | /* 40 | * Main Function, here for compilability 41 | */ 42 | int main() { 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct4.spl: -------------------------------------------------------------------------------- 1 | struct First { 2 | var a: Second; 3 | } 4 | 5 | struct Second { 6 | var b: Third; 7 | } 8 | 9 | struct Third { 10 | var c: First; 11 | } 12 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | /* 21 | * Structs 22 | */ 23 | struct Fifth_1; 24 | struct First_1; 25 | struct Fourth_1; 26 | struct Second_1; 27 | struct Third_1; 28 | 29 | typedef struct Fifth_1 { 30 | struct First_1* e_1; 31 | } Fifth_1; 32 | 33 | typedef struct First_1 { 34 | struct Second_1* a_1; 35 | } First_1; 36 | 37 | typedef struct Fourth_1 { 38 | struct Fifth_1* d_1; 39 | } Fourth_1; 40 | 41 | typedef struct Second_1 { 42 | struct Third_1* b_1; 43 | } Second_1; 44 | 45 | typedef struct Third_1 { 46 | struct Fourth_1* c_1; 47 | } Third_1; 48 | 49 | /* 50 | * Main Function, here for compilability 51 | */ 52 | int main() { 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct5.spl: -------------------------------------------------------------------------------- 1 | struct First { 2 | var a: Second; 3 | } 4 | 5 | struct Second { 6 | var b: Third; 7 | } 8 | 9 | struct Third { 10 | var c: Fourth; 11 | } 12 | 13 | struct Fourth { 14 | var d: Fifth; 15 | } 16 | 17 | struct Fifth { 18 | var e: First; 19 | } 20 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Includes 3 | */ 4 | #include 5 | #include 6 | 7 | /* 8 | * Preloaded Code 9 | */ 10 | typedef struct SPLArray { 11 | int length; 12 | void* arr[]; 13 | } SPLArray; 14 | 15 | void freeSPLArray (SPLArray* a) { 16 | free(a->arr); 17 | free(a); 18 | } 19 | 20 | /* 21 | * Structs 22 | */ 23 | struct First_1; 24 | struct Second_1; 25 | 26 | typedef struct First_1 { 27 | struct First_1* a_1; 28 | struct Second_1* b_1; 29 | int c_1; 30 | } First_1; 31 | 32 | typedef struct Second_1 { 33 | struct First_1* e_1; 34 | struct Second_1* f_1; 35 | int g_1; 36 | } Second_1; 37 | 38 | /* 39 | * Main Function, here for compilability 40 | */ 41 | int main() { 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /tests/spl/c_compiler/struct6.spl: -------------------------------------------------------------------------------- 1 | struct First { 2 | var a: First; 3 | var b: Second; 4 | var c: Int; 5 | } 6 | 7 | struct Second { 8 | var e: First; 9 | var f: Second; 10 | var g: Int; 11 | } 12 | -------------------------------------------------------------------------------- /tests/spl/concurrent/link-header.spl: -------------------------------------------------------------------------------- 1 | /** Header for link technique template for linearizable dictionaries. */ 2 | 3 | /* Files using this must define: 4 | - Node, unchanged(x), gammaSpatial(x), gammaG(x, I), gammaB(x, I) 5 | - FlowDom, domEq, domLeq, domPlus, domMult, domZero 6 | */ 7 | 8 | 9 | options "-symbexec" 10 | 11 | include "../include/flows.spl"; 12 | 13 | 14 | /** Node domain definitions */ 15 | 16 | datatype LockInfo = unlocked | locked(tid: Int) | dirtylock(dtid: Int) | lockTop; 17 | 18 | datatype NodeDom = nd(contents: Set, lockinfo: LockInfo); 19 | 20 | pure predicate ndLeq(a1: NodeDom, a2: NodeDom) { 21 | (forall x: Int :: x in a1.contents ==> x in a2.contents) 22 | && (a1.lockinfo == a2.lockinfo || a2.lockinfo == lockTop) 23 | } 24 | 25 | 26 | /** Definition of good condition, gamma */ 27 | 28 | pure function outset(x: Node, flmp: Map>) returns (O: Set) 29 | ensures forall k: Int :: k in O ==> (exists y: Node :: flmp[x][y].ks[k] > 0 @(matching O yields flmp[x][y].ks[k])) 30 | //{ { k: Int :: exists y: Node :: flmp[x][y].ks[k] > 0 } } // TODO why not? (see hashtbl.findNext) 31 | 32 | define gamma(x, I) { 33 | gammaSpatial(x) 34 | &*& ((gammaG(x, I) && (I.na.lockinfo == locked(TID) || I.na.lockinfo == unlocked) 35 | || gammaB(x, I) && I.na.lockinfo == dirtylock(TID)) 36 | && (forall k: Int :: k in I.na.contents ==> I.inf[x].ks[k] >= 1) 37 | && (forall k: Int, y: Node :: k !in I.na.contents || I.fm[x][y].ks[k] == 0) 38 | && (forall k: Int, y: Node, z: Node :: y == z 39 | || I.fm[x][y].ks[k] == 0 || I.fm[x][z].ks[k] == 0) 40 | // Inreach keyset \subseteq inset 41 | && (forall k: Int :: I.inf[x].ir[k] >= 1 && k !in outset(x, I.fm) ==> I.inf[x].ks[k] >= 1) 42 | // Inreach edgesets \subseteq normal edgesets 43 | && (forall k: Int, y: Node :: I.fm[x][y].ir[k] <= I.fm[x][y].ks[k]) 44 | // If k in inreach, then inreach edgeset is same as normal edgeset (for step) 45 | && (forall k: Int, y: Node :: I.inf[x].ir[k] >= 1 && I.inf[x].ks[k] <= 0 46 | && I.fm[x][y].ks[k] >= 1 ==> I.fm[x][y].ir[k] >= 1)) 47 | } 48 | 49 | 50 | var r: Node; 51 | 52 | define globalInt(I) { 53 | intValid(I) == true && r in I.FP && (forall k: Int :: I.inf[r].ks[k] == 1) 54 | && (forall n: Node, k: Int :: n != r ==> I.inf[n].ks[k] == 0) 55 | && I.FPo == {} && r != null 56 | } 57 | 58 | -------------------------------------------------------------------------------- /tests/spl/concurrent/sls.spl: -------------------------------------------------------------------------------- 1 | include "../include/flows.spl"; 2 | 3 | /** Flow domain definitions */ 4 | 5 | datatype FlowDom = pair(fst: Int, snd: Int); 6 | 7 | pure predicate domEq(p1: FlowDom, p2: FlowDom) { 8 | p1.fst == p2.fst && p1.snd == p2.snd 9 | } 10 | 11 | pure predicate domLeq(p1: FlowDom, p2: FlowDom) { 12 | p1.fst <= p2.snd && p1.snd <= p2.snd 13 | } 14 | 15 | pure function domPlus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 16 | { pair(p1.fst + p2.fst, p1.snd + p2.snd) } 17 | 18 | pure function domMult(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 19 | { pair(p1.fst * p2.fst, p1.snd * p2.snd) } 20 | 21 | pure function domZero() returns(p: FlowDom) { pair(0, 0) } 22 | 23 | datatype NodeDom = nd; 24 | 25 | pure predicate ndLeq(a1: NodeDom, a2: NodeDom) 26 | 27 | struct Node { 28 | var next: Node; 29 | var data: Int; 30 | } 31 | 32 | define unchanged(x) { x.next == old(x.next) && x.data == old(x.data) } 33 | 34 | /** Definition of good condition, gamma */ 35 | 36 | define gammaSpatial(x) { acc(x) } 37 | 38 | define gamma(x, I) { 39 | gammaSpatial(x) &*& I.inf[x].fst == 1 &*& I.inf[x].snd < x.data 40 | &*& (x.next == null && I.FPo == {} 41 | || x.next != null && I.FPo == {x.next} && I.fm[x][x.next] == pair(1, x.data)) 42 | } 43 | 44 | /** Lemmas */ 45 | 46 | procedure no_op(x: Node, I: Interface) 47 | requires N(x, I) &*& intValid(I) == true 48 | ensures N(x, I) 49 | { 50 | lemma_conc(x, I); 51 | var y := x.next; 52 | x.next := y; 53 | lemma_abs(x, I, I); 54 | sync(I, I); 55 | } 56 | -------------------------------------------------------------------------------- /tests/spl/concurrent/test_soundness1.spl: -------------------------------------------------------------------------------- 1 | include "../include/flows.spl"; 2 | 3 | /** Flow domain definitions */ 4 | 5 | datatype FlowDom = fd(pc: Int); 6 | 7 | datatype NodeDom = nd; 8 | 9 | function domPlus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 10 | { fd(p1.pc + p2.pc) } 11 | 12 | function domMult(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 13 | { fd(p1.pc * p2.pc) } 14 | 15 | function domZero() returns(p: FlowDom) { fd(0) } 16 | 17 | struct Node { 18 | var next: Node; 19 | } 20 | 21 | 22 | // Expect this to fail 23 | procedure test_valid2(I: Interface, x: Node) 24 | requires I == intUndef && I.FP == {x} && I.FPo == {} && (forall n: Node, o: Node :: I.inf[n] == fd(0) && I.fm[n][o] == fd(0)) 25 | ensures intValid(I) == true 26 | { 27 | lemma_int_valid_fold(I); 28 | } 29 | -------------------------------------------------------------------------------- /tests/spl/concurrent/tests.spl: -------------------------------------------------------------------------------- 1 | include "../include/flows.spl"; 2 | 3 | /** Flow domain definitions */ 4 | 5 | datatype FlowDom = fd(pc: Int); 6 | 7 | pure predicate domEq(p1: FlowDom, p2: FlowDom) { 8 | p1.pc == p2.pc 9 | } 10 | 11 | pure predicate domLeq(p1: FlowDom, p2: FlowDom) { 12 | p1.pc <= p2.pc 13 | } 14 | 15 | pure function domPlus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 16 | { fd(p1.pc + p2.pc) } 17 | 18 | pure function domMult(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 19 | { fd(p1.pc * p2.pc) } 20 | 21 | pure function domZero() returns(p: FlowDom) { fd(0) } 22 | 23 | datatype NodeDom = nd; 24 | 25 | pure predicate ndLeq(a1: NodeDom, a2: NodeDom) 26 | 27 | struct Node { 28 | var next: Node; 29 | } 30 | 31 | define unchanged(x) { x.next == old(x.next) } 32 | 33 | define gammaSpatial(x) { true } 34 | 35 | define gamma(x, I) { true } 36 | 37 | procedure test_valid1(I1: Interface, I2: Interface) 38 | requires ! intValid(I1) && intValid(intComp(I1, I2)) 39 | ensures false 40 | {} 41 | 42 | procedure test_decomp(x: Node, I: Interface) 43 | returns (I1: Interface, I2: Interface) 44 | requires Gr(I) &*& x in I.FP 45 | requires intValid(I) == true 46 | ensures N(x, I1) &*& Gr(I2) 47 | ensures intValid(I1) == true && intValid(I2) == true 48 | { 49 | I1, I2 := lemma_decomp(x, I); 50 | } 51 | 52 | procedure test_return1(x: Int, y: Int) returns (z: Int) 53 | requires x < 3 && y >= 4 54 | ensures x < z && z < y 55 | { 56 | return 3; 57 | } 58 | -------------------------------------------------------------------------------- /tests/spl/counter/counter_simple.spl: -------------------------------------------------------------------------------- 1 | struct Counter { 2 | ghost var n: Int; 3 | var c: Cell; 4 | } 5 | 6 | struct Cell { 7 | var data: Int; 8 | } 9 | 10 | predicate counter(this: Counter) { 11 | acc(this) &*& acc(this.c) &*& 12 | 0 <= this.n &*& 13 | this.n == this.c.data 14 | } 15 | 16 | procedure NewCounter(initValue: Int) 17 | returns (this: Counter) 18 | requires 0 <= initValue 19 | ensures counter(this) 20 | ensures this.n == initValue 21 | { 22 | this := new Counter; 23 | this.c := new Cell; 24 | this.n := initValue; 25 | this.c.data := initValue; 26 | } 27 | 28 | procedure test(this: Counter) 29 | requires counter(this) 30 | { 31 | assert counter(this); 32 | assume false; 33 | } 34 | 35 | procedure FreeCounter(this: Counter) 36 | requires counter(this) 37 | { 38 | free this.c; 39 | free this; 40 | } 41 | 42 | procedure Inc(this: Counter, implicit ghost FP1: Set, implicit ghost FP2: Set) 43 | requires counter(this) && (acc(FP1) &*& acc(FP2)) 44 | ensures counter(this) && (acc(FP1) &*& acc(FP2)) 45 | ensures old(this.n) < this.n 46 | { 47 | this.n := this.n + 1; 48 | this.c.data := this.c.data + 1; 49 | } 50 | 51 | procedure Main() { 52 | var c := NewCounter(23); 53 | Inc(c); 54 | Inc(c); 55 | pure assert c.n >= 25; 56 | FreeCounter(c); 57 | } 58 | 59 | 60 | -------------------------------------------------------------------------------- /tests/spl/counter/counter_two_cells.spl: -------------------------------------------------------------------------------- 1 | struct Counter { 2 | ghost var n: Int; 3 | var c1: Cell; 4 | var c2: Cell; 5 | } 6 | 7 | struct Cell { 8 | var data: Int; 9 | } 10 | 11 | 12 | procedure NewCounter(initValue: Int) 13 | returns (this: Counter) 14 | requires 0 <= initValue 15 | ensures acc(this) &*& acc(this.c1) &*& acc(this.c2) 16 | ensures 0 <= this.n &*& this.n == this.c1.data 17 | ensures this.n == initValue 18 | ensures this.c2.data == 0 19 | { 20 | this := new Counter; 21 | this.c1 := new Cell; 22 | this.c2 := new Cell; 23 | this.n := initValue; 24 | this.c1.data := initValue; 25 | this.c2.data := 0; 26 | } 27 | 28 | procedure FreeCounter(this: Counter) 29 | requires acc(this) &*& acc(this.c1) &*& acc(this.c2) 30 | { 31 | free this.c1; 32 | free this.c2; 33 | free this; 34 | } 35 | 36 | procedure Inc(this: Counter) 37 | requires acc(this) &*& acc(this.c1) 38 | requires 0 <= this.n &*& this.n == this.c1.data 39 | ensures acc(this) &*& acc(this.c1) &*& 0 <= this.n &*& this.n == this.c1.data 40 | ensures old(this.n) < this.n 41 | { 42 | this.n := this.n + 1; 43 | this.c1.data := this.c1.data + 1; 44 | } 45 | 46 | procedure Main() { 47 | var c := NewCounter(23); 48 | Inc(c); 49 | Inc(c); 50 | pure assert c.n >= 25; 51 | pure assert c.c2.data == 0; 52 | FreeCounter(c); 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /tests/spl/counter/counter_very_simple.spl: -------------------------------------------------------------------------------- 1 | struct Counter { 2 | ghost var n: Int; 3 | var c: Cell; 4 | } 5 | 6 | struct Cell { 7 | var data: Int; 8 | } 9 | 10 | procedure NewCounter(initValue: Int) 11 | returns (this: Counter) 12 | requires 0 <= initValue 13 | ensures acc(this) &*& acc(this.c) &*& 0 <= this.n &*& this.n == this.c.data 14 | ensures this.n == initValue 15 | { 16 | this := new Counter; 17 | this.c := new Cell; 18 | this.n := initValue; 19 | this.c.data := initValue; 20 | } 21 | 22 | procedure FreeCounter(this: Counter) 23 | requires acc(this) &*& acc(this.c) 24 | { 25 | free this.c; 26 | free this; 27 | } 28 | 29 | procedure Inc(this: Counter) 30 | requires acc(this) &*& acc(this.c) &*& 0 <= this.n &*& this.n == this.c.data 31 | ensures acc(this) &*& acc(this.c) &*& 0 <= this.n &*& this.n == this.c.data 32 | ensures old(this.n) < this.n 33 | { 34 | this.n := this.n + 1; 35 | this.c.data := this.c.data + 1; 36 | } 37 | 38 | procedure Main() { 39 | var c := NewCounter(23); 40 | Inc(c); 41 | Inc(c); 42 | pure assert c.n >= 25; 43 | FreeCounter(c); 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_concat.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_concat(start1: Node, end1: Node, start2: Node, end2: Node) 4 | returns (start: Node, end: Node) 5 | requires dlseg(start1, null, null, end1); 6 | requires dlseg(start2, null, null, end2); 7 | ensures dlseg(start, null, null, end); 8 | { 9 | if (start2 == null) { 10 | return start1, end1; 11 | } else if (start1 == null) { 12 | return start2, end2; 13 | } else { 14 | end1.next := start2; 15 | start2.prev := end1; 16 | return start1, end2; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_copy.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_copy(a: Node, b: Node) returns (c: Node, d: Node) 4 | requires dlseg(a, null, null, b); 5 | ensures dlseg(a, null, null, b) &*& dlseg(c, null, null, d); 6 | { 7 | c, d := null, null; 8 | var curr: Node, old_curr: Node; 9 | curr := a; 10 | old_curr := null; 11 | while (curr != null) 12 | invariant (curr == a && old_curr == null || old_curr.next |-> curr) -** 13 | dlseg(a, null, null, b); 14 | invariant dlseg(c, null, null, d); 15 | { 16 | var old_d: Node; 17 | old_curr := curr; 18 | old_d := d; 19 | d := new Node; 20 | d.next := null; 21 | d.prev := old_d; 22 | if (old_d != null) { 23 | old_d.next := d; 24 | } else { 25 | c := d; 26 | } 27 | curr := curr.next; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_dancing.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | // Implementation of Dancing Links (see Problem 3 of Verify This Competition 2015) 4 | 5 | procedure remove(l: Node, x: Node, ghost e: Node, implicit ghost FP: Set) 6 | requires (acc(x.prev) &*& acc(x) &*& acc(x.next)) -** dlseg(l, null, null, e) && acc(FP) 7 | ensures ((acc(x.prev) &*& acc(x.next)) -** dlseg(l, null, null, e) && acc(FP -- {x})) &*& acc(x) 8 | ensures x.next.prev == x.prev 9 | ensures x.next == x.prev.next 10 | ensures forall z1 in FP -- {x}, z2 in FP -- {x} :: Reach(old(next), z1, z2) ==> Reach(next, z1, z2) 11 | { 12 | var xn := x.next; 13 | xn.prev := x.prev; 14 | var xp := x.prev; 15 | xp.next := x.next; 16 | } 17 | 18 | 19 | procedure readd(l: Node, x: Node, ghost e: Node) 20 | requires ((acc(x.prev) &*& acc(x.next)) -** dlseg(l, null, null, e)) &*& acc(x) 21 | requires x.next.prev == x.prev 22 | requires x.next == x.prev.next 23 | ensures (acc(x.prev) &*& acc(x) &*& acc(x.next)) -** dlseg(l, null, null, e) 24 | { 25 | var xn := x.next; 26 | xn.prev := x; 27 | var xp := x.prev; 28 | xp.next := x; 29 | } 30 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_dancing_simple.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure remove(l: Node, x: Node, ghost e: Node) 4 | requires (acc(x.prev) &*& acc(x) &*& acc(x.next)) -** dlseg(l, null, null, e) 5 | ensures ((acc(x.prev) &*& acc(x.next)) -** dlseg(l, null, null, e)) &*& acc(x) 6 | ensures x.next.prev == x.prev 7 | ensures x.next == x.prev.next 8 | { 9 | var xn := x.next; 10 | xn.prev := x.prev; 11 | var xp := x.prev; 12 | xp.next := x.next; 13 | } 14 | 15 | 16 | procedure readd(l: Node, x: Node, ghost e: Node) 17 | requires ((acc(x.prev) &*& acc(x.next)) -** dlseg(l, null, null, e)) &*& acc(x) 18 | requires x.next.prev == x.prev 19 | requires x.next == x.prev.next 20 | ensures (acc(x.prev) &*& acc(x) &*& acc(x.next)) -** dlseg(l, null, null, e) 21 | { 22 | var xn := x.next; 23 | xn.prev := x; 24 | var xp := x.prev; 25 | xp.next := x; 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_dispose.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_dispose(a: Node, b: Node) 4 | requires dlseg(a, null, null, b); 5 | ensures emp; 6 | { 7 | var prv: Node; 8 | prv := null; 9 | while (a != null) 10 | invariant dlseg(a, prv, null, b); 11 | { 12 | prv := a; 13 | a := a.next; 14 | free prv; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_filter.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_filter(a: Node, b: Node) returns (c: Node, d: Node) 4 | requires dlseg(a, null, null, b); 5 | ensures dlseg(c, null, null, d); 6 | { 7 | var prv: Node, curr: Node; 8 | c, d := a, b; 9 | prv := null; 10 | curr := c; 11 | while (curr != null) 12 | invariant dlseg(c, null, curr, prv) &*& dlseg(curr, prv, null, d); 13 | { 14 | var nondet: Bool, old_curr: Node; 15 | old_curr := curr; 16 | curr := curr.next; 17 | if (nondet) { 18 | if (prv != null) { 19 | prv.next := curr; 20 | } else { 21 | c := curr; 22 | } 23 | if (curr != null) { 24 | curr.prev := prv; 25 | } else { 26 | d := prv; 27 | } 28 | free old_curr; 29 | } else { 30 | prv := old_curr; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_insert.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_insert(a: Node, b: Node, elt: Node) returns (c: Node, d: Node) 4 | requires dlseg(a, null, null, b) &*& acc(elt); 5 | ensures dlseg(c, null, null, d); 6 | { 7 | if (a == null) { 8 | elt.prev := null; 9 | elt.next := null; 10 | return elt, elt; 11 | } else { 12 | c, d := a, b; 13 | var curr := c; 14 | var nondet: Bool; 15 | while (nondet && curr.next != null) 16 | invariant acc(curr) -** dlseg(c, null, null, d); 17 | { 18 | curr := curr.next; 19 | havoc nondet; 20 | } 21 | elt.next := curr; 22 | var prv := curr.prev; 23 | curr.prev := elt; 24 | elt.prev := prv; 25 | if (prv != null) { 26 | prv.next := elt; 27 | } else { 28 | c := elt; 29 | } 30 | return c, d; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_remove.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_remove(a: Node, b: Node) returns (c: Node, d: Node) 4 | requires dlseg(a, null, null, b); 5 | ensures dlseg(c, null, null, d); 6 | { 7 | if (a == null) { 8 | return a, b; 9 | } else if (a == b) { 10 | free a; 11 | return null, null; 12 | } else { 13 | var curr: Node; 14 | c, d := a, b; 15 | curr := c; 16 | 17 | var nondet: Bool; 18 | while (nondet && curr.next != null) 19 | invariant acc(curr) -** dlseg(c, null, null, d); 20 | { 21 | curr := curr.next; 22 | havoc nondet; 23 | } 24 | 25 | var nxt: Node; 26 | nxt := curr.next; 27 | var prv: Node; 28 | prv := curr.prev; 29 | if (prv != null) { 30 | prv.next := nxt; 31 | } else { 32 | c := nxt; 33 | } 34 | if (nxt != null) { 35 | nxt.prev := prv; 36 | } else { 37 | d := prv; 38 | } 39 | free curr; 40 | return c, d; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_reverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_reverse(start: Node, end: Node) 4 | requires dlseg(start, null, null, end); 5 | ensures dlseg(end, null, null, start); 6 | { 7 | var curr: Node, prv: Node; 8 | curr := start; 9 | prv := null; 10 | while (curr != null) 11 | invariant dlseg(curr, prv, null, end); 12 | invariant dlseg(prv, curr, null, start); 13 | { 14 | var tmp: Node; 15 | tmp := curr; 16 | curr := curr.next; 17 | tmp.next := prv; 18 | prv := tmp; 19 | prv.prev := curr; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_test.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_test(a: Node, b: Node, c: Node, d: Node) 4 | requires dlseg(a, null, b, c); 5 | requires dlseg(b, c, null, d); 6 | ensures dlseg(a, null, null, d); 7 | { 8 | } 9 | 10 | procedure dl_traverse2(lst: Node, tsl: Node) 11 | requires dlseg(lst, null, null, tsl); 12 | ensures dlseg(lst, null, null, tsl); 13 | { 14 | var curr: Node, nxt: Node; 15 | curr := tsl; 16 | nxt := null; 17 | while (curr != null) 18 | invariant dlseg(lst, null, nxt, curr); 19 | invariant dlseg(nxt, curr, null, tsl); 20 | { 21 | nxt := curr; 22 | curr := curr.prev; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /tests/spl/dl/dl_traverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | procedure dl_traverse(lst: Node, ghost a: Node, ghost b: Node) 4 | requires dlseg(lst, a, null, b) 5 | ensures dlseg(lst, a, null, b) 6 | { 7 | var curr, prv := lst, a; 8 | while (curr != null) 9 | invariant (curr == null || acc(curr)) -** dlseg(lst, a, null, b) 10 | { 11 | prv := curr; 12 | curr := curr.next; 13 | } 14 | } 15 | 16 | procedure dl_traverse2(a: Node, b: Node, c: Node, d: Node) 17 | requires dlseg(a, b, c, d) 18 | ensures dlseg(a, b, c, d) 19 | { 20 | var curr: Node, prv: Node; 21 | curr := a; 22 | prv := b; 23 | while (curr != c) 24 | invariant (curr == c || acc(curr)) -** dlseg(a, b, c, d) 25 | { 26 | prv := curr; 27 | curr := curr.next; 28 | } 29 | } 30 | 31 | procedure dl_traverse3(a: Node, b: Node, c: Node, d: Node) 32 | requires dlseg(a, b, c, d) 33 | ensures dlseg(a, b, c, d) 34 | { 35 | var curr: Node, prv: Node; 36 | curr := d; 37 | prv := c; 38 | while (curr != b) 39 | invariant dlseg(a, b, c, d) && (dlseg(a, b, prv, curr) &*& dlseg(prv, curr, c, d)) 40 | { 41 | prv := curr; 42 | curr := curr.prev; 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /tests/spl/entailments/bounded_lists.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure test1(x: Node, y: Node) 4 | requires x.next |-> y &*& x != y 5 | ensures lseg(x,y) 6 | {} 7 | 8 | procedure test2(x: Node, y: Node) 9 | requires x.next |-> y &*& x != y && x.data == 2 10 | ensures ulseg(x,y,0) 11 | {} 12 | 13 | procedure test3(x: Node, y: Node) 14 | requires ulseg(x,y,2) 15 | ensures ulseg(x,y,0) 16 | {} 17 | 18 | -------------------------------------------------------------------------------- /tests/spl/flows/ccm.spl: -------------------------------------------------------------------------------- 1 | /** {Spec} Theory of cancellative commutative monoids (CCMs) */ 2 | 3 | options "-simplearrays -propreads -abspreds -stratify" 4 | 5 | 6 | // The type of the flow domain 7 | type FlowDom 8 | 9 | // The monoid operation 10 | function domPlus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 11 | 12 | // Partial inverse of monoid operation 13 | function domMinus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 14 | 15 | // Neutral element 16 | function domZero() returns (p: FlowDom) 17 | 18 | // Refinement predicate for flow domain values 19 | pure predicate domValid(p: FlowDom) 20 | 21 | // Unproven lemmas stated below are the axioms of CCMs. 22 | // They are proven for each specific CCM that we consider. 23 | 24 | // domZero is unit of domPlus 25 | lemma domZero_unit(p: FlowDom) 26 | ensures domPlus(p, domZero) == p 27 | 28 | // domPlus is associative 29 | lemma domPlus_assoc(p1: FlowDom, p2: FlowDom, p3: FlowDom) 30 | ensures domPlus(p1, domPlus(p2, p3)) == domPlus(domPlus(p1, p2), p3) 31 | 32 | // domPlus is commutative 33 | lemma domPlus_comm(p1: FlowDom, p2: FlowDom) 34 | ensures domPlus(p1, p2) == domPlus(p2, p1) 35 | 36 | // domPlus is cancellative 37 | lemma domPlus_canc(p1: FlowDom, p2: FlowDom, p3: FlowDom) 38 | requires domPlus(p1, p2) == domPlus(p1, p3) 39 | ensures p2 == p3 40 | 41 | // domMinus is partial inverse of domPlus 42 | lemma domMinus_pinv(p1: FlowDom, p2: FlowDom) 43 | ensures domMinus(domPlus(p1, p2), p1) == p2 44 | 45 | // domZero is valid 46 | lemma domZero_valid() 47 | ensures domValid(domZero); 48 | 49 | // Validity is preserved by domPlus 50 | lemma domPlus_valid(p1: FlowDom, p2: FlowDom) 51 | requires domValid(p1) && domValid(p2) 52 | ensures domValid(domPlus(p1, p2)) 53 | 54 | /** {Spec} End of CCM axioms */ 55 | 56 | lemma domMinus_unit(p: FlowDom) 57 | ensures domMinus(p, domZero) == p 58 | { 59 | domMinus_pinv(domZero, p); 60 | domPlus_comm(domZero, p); 61 | domZero_unit(p); 62 | } 63 | 64 | lemma domMinus_plus(p1: FlowDom, p2: FlowDom, p3: FlowDom) 65 | requires p1 == domPlus(p2, p3) 66 | ensures p2 == domMinus(p1, p3) 67 | { 68 | domPlus_comm(p2, p3); 69 | domMinus_pinv(p3, p2); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /tests/spl/flows/css.spl: -------------------------------------------------------------------------------- 1 | /** {Spec} Abstract specification of concurrent search structures */ 2 | 3 | 4 | datatype DOp = searchOp | insertOp | deleteOp; 5 | 6 | /* The predicate Ψ in Figure 5 of the paper */ 7 | predicate Psi(dop: DOp, k: K, C: Set, C1: Set, res: Bool) { 8 | (dop == searchOp && C1 == C && (res == k in C)) 9 | || (dop == insertOp && C1 == C ++ {k} && (res == k !in C)) 10 | || (dop == deleteOp && C1 == C -- {k} && (res == k in C)) 11 | } -------------------------------------------------------------------------------- /tests/spl/flows/give-up.spl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wies/grasshopper/80b86679d02ee5a5ab9851dadb1877d105884cc2/tests/spl/flows/give-up.spl -------------------------------------------------------------------------------- /tests/spl/flows/link.spl: -------------------------------------------------------------------------------- 1 | /** {Spec} Flow domain for multisets over some element type K */ 2 | 3 | include "css.spl" 4 | include "flows.spl" 5 | include "multipair-ccm.spl" 6 | 7 | type FlowDom = MultiPair 8 | 9 | lemma domMinus_inv(m1: MultiPair, m2: MultiPair) 10 | ensures m1 == domPlus(m2, domMinus(m1, m2)) 11 | { 12 | pure assert forall k: K :: m1.is[k] == domPlus(m2, domMinus(m1, m2)).is[k] with { 13 | pure assert m1.is[k] == m2.is[k] + (m1.is[k] - m2.is[k]); 14 | pure assert m1.is[k] == m2.is[k] + domMinus(m1, m2).is[k]; 15 | } 16 | pure assert forall k: K :: m1.ls[k] == domPlus(m2, domMinus(m1, m2)).ls[k] with { 17 | pure assert m1.ls[k] == m2.ls[k] + (m1.ls[k] - m2.ls[k]); 18 | pure assert m1.ls[k] == m2.ls[k] + domMinus(m1, m2).ls[k]; 19 | } 20 | } 21 | 22 | pure function KS() returns (res: Set) 23 | 24 | /* Definitions of predicates used in link template proof in Iris */ 25 | 26 | define in_inset(k, I, n) { 27 | I.inf[n].is[k] > 0 28 | } 29 | 30 | define in_linkset(k, I, n) { 31 | I.inf[n].ls[k] > 0 32 | } 33 | 34 | define in_outset(k, I, n) { 35 | I.out[n].is[k] > 0 || I.out[n].ls[k] > 0 36 | } 37 | 38 | predicate in_outsets(k: K, I: Interface) 39 | { 40 | exists y: Node :: in_outset(k, I, y) 41 | } 42 | 43 | function keyset(I: Interface, n: Node) returns (res: Set) 44 | { 45 | { k: K :: in_inset(k, I, n) && !(in_outsets(k, I)) } 46 | } 47 | 48 | 49 | /* Global invariant \phi that needs to be maintained */ 50 | pure predicate globalinv(root: Node, I: Interface) { 51 | intValid(I) 52 | && root in I.dom 53 | && (forall k: K, n: Node :: !(in_outset(k, I, n))) 54 | && (forall k: K :: k in KS 55 | ==> in_inset(k, I, root) && in_linkset(k, I, root)) 56 | && (forall k: K, n: Node :: n != root 57 | ==> !(in_inset(k, I, n) && !(in_linkset(k, I, n)))) 58 | } 59 | 60 | /* Node-level invariant \gamma that needs to be maintained */ 61 | pure predicate nodeinv(n: Node, I: Interface, C: Set) { 62 | (forall k1: K :: in_linkset(k1, I, n) && !(in_outsets(k1, I)) 63 | ==> in_inset(k1, I, n)) 64 | } -------------------------------------------------------------------------------- /tests/spl/flows/lock-coupling.spl: -------------------------------------------------------------------------------- 1 | /** Flow domain setup for verifying lock-coupling template implementations */ 2 | 3 | /** Flow domain for multisets over some element type K */ 4 | 5 | include "inset-flows.spl" 6 | include "multiset-ccm.spl" 7 | 8 | 9 | /* The node-level invariant (\gamma in the paper). */ 10 | predicate nodeinv(root: Node, n: Node, I: Interface, C: Set) 11 | { 12 | I.dom == {n} 13 | && C <= keyset(I, n) 14 | && (forall k: K :: I.inf[n][k] <= 1) 15 | && (n == root ==> (forall k1 in KS :: in_outsets(k1, I))) 16 | } 17 | 18 | -------------------------------------------------------------------------------- /tests/spl/flows/ordered_type.spl: -------------------------------------------------------------------------------- 1 | // An ordered type 2 | type K 3 | 4 | /* 5 | pure function compare(x: K, y: K) returns (res: Int) 6 | pure predicate lt(x: K, y: K) 7 | pure predicate le(x: K, y: K) 8 | 9 | const bot: K 10 | const top: K 11 | 12 | auto lemma bot_smallest(x: K) 13 | ensures !lt(x, bot) 14 | 15 | auto lemma top_largest(x: K) 16 | ensures !lt(top, x) 17 | 18 | auto lemma lt_irreflexive(x: K) 19 | ensures !lt(top, x) 20 | */ 21 | 22 | pure predicate lt(x: K, y: K) 23 | 24 | const bot: K 25 | const top: K 26 | 27 | axiom forall a: K :: !lt(a, bot) 28 | axiom forall a: K :: !lt(top, a) 29 | axiom bot != top 30 | 31 | axiom forall a: K :: !lt(a, a) 32 | axiom forall a: K, b: K :: !lt(a, b) || !lt(b, a) 33 | axiom forall a: K, b: K :: lt(a, b) || lt(b, a) || a == b 34 | axiom forall a: K, b: K, c: K :: lt(a, b) && lt(b, c) ==> lt(a, c) 35 | 36 | function le(x: K, y: K) returns (res: Bool) { 37 | lt(x, y) || x == y 38 | } 39 | 40 | 41 | function compare(x: K, y: K) returns (res: Int) 42 | { 43 | x == y ? 0 : (lt(x, y) ? -1 : 1) 44 | } -------------------------------------------------------------------------------- /tests/spl/ftp/askIP.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/console.spl"; 2 | include "../array/copy_byte_slice.spl"; 3 | include "../array/string.spl"; 4 | include "../../../lib/socket.spl"; 5 | 6 | procedure askIP(port: Array) 7 | returns (ip: SocketAddressIP4) 8 | requires byte_array(port) 9 | ensures byte_array(port) 10 | ensures port == old(port) && port.length == old(port.length) 11 | ensures ip == null || socket_addr_4(ip) 12 | { 13 | var writtenPrompt := new Array(46); 14 | writtenPrompt := "Enter IP of server (hit enter for localhost):"; 15 | 16 | var written := gputs(writtenPrompt); 17 | free(writtenPrompt); 18 | var getip := new Array(50); 19 | 20 | var numChars := ggets(getip); 21 | var dataAddr: SocketAddressIP4 := null; 22 | if (numChars < 1) { 23 | free(getip); 24 | return dataAddr; 25 | } 26 | getip[numChars-1] := int2byte(0); 27 | if (numChars != 1){ 28 | dataAddr := get_address4(getip, port); 29 | } else { 30 | dataAddr := get_address4(null, port); 31 | } 32 | free(getip); 33 | return dataAddr; 34 | } 35 | -------------------------------------------------------------------------------- /tests/spl/ftp/doWeUpload.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/console.spl"; 2 | include "../array/string.spl"; 3 | 4 | procedure doWeUpload() 5 | returns (res: Int) 6 | ensures (res == -1) || (res == 1) || (res == 0) 7 | { 8 | 9 | var updown := new Array(30); 10 | 11 | var text := new Array(28); 12 | text := "upload (u) or download (d):"; 13 | var written := gputs(text); 14 | free(text); 15 | if (!written) { 16 | free(updown); 17 | return -1; 18 | } else { 19 | var numChars := ggets(updown); 20 | 21 | if (numChars == 2) { 22 | var copy := new Array(2); 23 | copy[0] := updown[0]; 24 | copy[1] := int2byte(0); 25 | free(updown); 26 | // updown[1] := int2byte(0); 27 | var uChar := new Array(2); 28 | uChar := "u"; 29 | 30 | if (gstrcmp(uChar, copy) == 0) { 31 | free(uChar); 32 | // free(updown); 33 | free(copy); 34 | return 1; 35 | } else { 36 | free(uChar); 37 | //free(updown); 38 | free(copy); 39 | return 0; 40 | } 41 | } else { 42 | free(updown); 43 | return -1; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /tests/spl/ftp/response.spl: -------------------------------------------------------------------------------- 1 | include "../array/string.spl"; 2 | 3 | procedure checkServerResponseUSER(response: Array) 4 | returns (success: Bool) 5 | requires byte_array(response) 6 | ensures byte_array(response) 7 | { 8 | var ack := atoiG(response); 9 | if ((ack == 200) || 10 | (ack == 230) || 11 | (ack == 234) || 12 | (ack == 331) ) 13 | success := true; 14 | else 15 | success := false; 16 | return success; 17 | } 18 | 19 | procedure checkServerResponsePASS(response: Array) 20 | returns (success: Bool) 21 | requires byte_array(response) 22 | ensures byte_array(response) 23 | { 24 | var ack := atoiG(response); 25 | if ((ack == 200) || 26 | (ack == 202) || 27 | (ack == 230) || 28 | (ack == 234)) 29 | success := true; 30 | else 31 | success := false; 32 | return success; 33 | } 34 | 35 | procedure checkServerResponse_200(response: Array) 36 | returns (success: Bool) 37 | requires byte_array(response) 38 | ensures byte_array(response) 39 | { 40 | var ack := atoiG(response); 41 | if (ack == 200) 42 | return true; 43 | else 44 | return false; 45 | } 46 | 47 | procedure checkServerResponse_213(response: Array) 48 | returns (success: Bool) 49 | requires byte_array(response) 50 | ensures byte_array(response) 51 | { 52 | var ack := atoiG(response); 53 | if (ack == 213) 54 | return true; 55 | else 56 | return false; 57 | } 58 | 59 | procedure checkServerResponse_200_150(response: Array) 60 | returns (success: Bool) 61 | requires byte_array(response) 62 | ensures byte_array(response) 63 | { 64 | var ack := atoiG(response); 65 | if ((ack == 200) || 66 | (ack == 150)) 67 | success := true; 68 | else 69 | success := false; 70 | return success; 71 | } 72 | 73 | procedure checkServerResponse_200_226_250(response: Array) 74 | returns (success: Bool) 75 | requires byte_array(response) 76 | ensures byte_array(response) 77 | { 78 | var ack := atoiG(response); 79 | if ((ack == 200) || 80 | (ack == 226) || 81 | (ack == 250)) 82 | success := true; 83 | else 84 | success := false; 85 | return success; 86 | } 87 | -------------------------------------------------------------------------------- /tests/spl/include/assoc_list.spl: -------------------------------------------------------------------------------- 1 | 2 | struct Node { 3 | var next: Node; 4 | var key: Int; 5 | var data: Int; 6 | } 7 | 8 | predicate lseg(x: Node, y: Node) { 9 | acc({ z: Node :: Btwn(next, x, z, y) && z != y }) &*& Btwn(next, x, y, y) 10 | } 11 | 12 | predicate lseg_strictly_increasing(x: Node, FP: Set) { 13 | forall y: Node, z: Node :: y in FP && z in FP && Btwn(next,x,y,z) ==> y.key < z.key || y == z 14 | } 15 | 16 | function key_witness(k: Int, FP: Set) 17 | returns (res: Node) 18 | requires acc(FP) 19 | ensures forall x in FP :: x == key_witness(x.key, FP) 20 | 21 | function keys(FP: Set) 22 | returns (K: Set) 23 | requires acc(FP) 24 | ensures forall x in FP :: x.key in K 25 | ensures forall v in K :: key_witness(v, FP) in FP 26 | ensures forall v: Int :: v !in K ==> key_witness(v, FP) == null 27 | ensures forall v in K :: v == key_witness(v, FP).key @(matching v yields key_witness(v, FP).key) 28 | ensures forall v in K, FP1: Set :: key_witness(v, FP) in FP1 ==> key_witness(v, FP) == key_witness(v, FP1) 29 | 30 | /* 31 | function keys(FP: Set) 32 | returns (K: Set) 33 | requires acc(FP) 34 | { 35 | { v: Int :: exists x: Node :: x in FP && x.key == v } 36 | } 37 | */ 38 | 39 | predicate list_map(x: Node, y: Node, D: Set, C: Map) { 40 | exists FP: Set :: 41 | lseg(x, y) && acc(FP) &*& 42 | lseg_strictly_increasing(x, FP) &*& 43 | D == keys(FP) &*& 44 | (forall n in FP :: n.key.C == n.data @(matching n.data yields n.key.C) ) 45 | } 46 | -------------------------------------------------------------------------------- /tests/spl/include/bag.spl: -------------------------------------------------------------------------------- 1 | // axiomatization of multisets from "Combining Multisets with Integers" by Calogero G. Zarba. 2 | 3 | type Value; 4 | 5 | type Bag; 6 | 7 | function min(i1: Int, i2: Int) 8 | returns (i3: Int) 9 | ensures (i1 < i2 && i1 == i3) || (i1 >= i2 && i2 == i3) 10 | 11 | function max(i1: Int, i2: Int) 12 | returns (i3: Int) 13 | ensures (i1 > i2 && i1 == i3) || (i1 <= i2 && i2 == i3) 14 | 15 | function difference_witness(b1: Bag, b2: Bag) 16 | returns (v: Value) 17 | ensures difference_witness(b1, b2) == difference_witness(b2, b1) 18 | 19 | function count(v: Value, b: Bag) 20 | returns (c: Int) 21 | 22 | axiom (forall v: Value, b: Bag :: count(v, b) >= 0 23 | @(matching v, b yields count(v, b))); 24 | axiom forall b1: Bag, b2: Bag :: b1 != b2 ==> count(difference_witness(b1, b2), b1) != count(difference_witness(b1, b2), b2) 25 | @(matching b1, b2 yields count(difference_witness(b1, b2), b1)) 26 | @(matching b1, b2 yields count(difference_witness(b1, b2), b2)); 27 | 28 | function empty_bag() 29 | returns (b: Bag) 30 | ensures forall v: Value :: count(v, b) == 0 31 | 32 | function make_bag(v: Value, n: Int) 33 | returns (b: Bag) 34 | ensures count(v, b) == n 35 | ensures forall w: Value :: w != v ==> count(w, b) == 0 36 | 37 | predicate memberN(v: Value, n: Int, b: Bag) 38 | { 39 | count(v, b) >= n 40 | } 41 | 42 | predicate member(v: Value, b: Bag) 43 | { 44 | memberN(v, 1, b) 45 | } 46 | 47 | function intersection(b1: Bag, b2: Bag) 48 | returns (b3: Bag) 49 | ensures forall v: Value :: count(v, b3) == min(count(v, b1), count(v, b2)) 50 | @(matching v yields min(count(v, b1), count(v, b2))) 51 | 52 | function union(b1: Bag, b2: Bag) 53 | returns (b3: Bag) 54 | ensures forall v: Value :: count(v, b3) == max(count(v, b1), count(v, b2)) 55 | @(matching v yields max(count(v, b1), count(v, b2))) 56 | 57 | function sum(b1: Bag, b2: Bag) 58 | returns (b3: Bag) 59 | ensures forall v: Value :: count(v, b3) == count(v, b1) + count(v, b2) 60 | @(matching v yields count(v, b1) + count(v, b2)) 61 | 62 | -------------------------------------------------------------------------------- /tests/spl/include/bstree_rec.spl: -------------------------------------------------------------------------------- 1 | // Structure and predicate declarations for binary search trees 2 | 3 | struct Node { 4 | var left: Node; 5 | var right: Node; 6 | var data: Int; 7 | } 8 | 9 | predicate tree(r: Node) { 10 | r == null || 11 | r != null &*& acc(r) &*& tree(r.left) &*& tree(r.right) 12 | } 13 | 14 | predicate bst(r: Node) { 15 | r == null || 16 | (exists FP_L: Set, FP_R: Set :: 17 | r != null &*& acc(r) &*& (bst(r.left) && acc(FP_L)) &*& (bst(r.right) && acc(FP_R)) 18 | &*& (forall x in FP_L :: x.data <= r.data) 19 | &*& (forall x in FP_R :: r.data <= x.data) 20 | ) 21 | } 22 | 23 | 24 | function data_witness(v: Int, FP: Set) 25 | returns (res: Node) 26 | requires acc(FP) 27 | ensures forall x in FP :: x == data_witness(x.data, FP) 28 | 29 | function content(FP: Set) returns (C: Set) 30 | requires acc(FP) 31 | ensures forall v: Int :: v !in C ==> data_witness(v, FP) == null 32 | ensures forall x in FP :: x.data in content(FP) 33 | ensures forall v in C :: data_witness(v, FP) in FP; 34 | ensures forall v in C :: v == data_witness(v, FP).data 35 | @(matching v yields data_witness(v, FP).data); 36 | 37 | predicate tree_set(r: Node, Content: Set) { 38 | r == null && Content == {} || 39 | (exists FP_L: Set, FP_R: Set, C_L: Set, C_R: Set :: 40 | r != null &*& acc(r) &*& (tree_set(r.left, C_L) && acc(FP_L)) &*& (tree_set(r.right, C_R) && acc(FP_R)) 41 | &*& (forall x in FP_L :: x.data <= r.data) 42 | &*& (forall x in FP_R :: r.data <= x.data) 43 | &*& Content == {r.data} ++ C_L ++ C_R 44 | &*& C_L == content(FP_L) 45 | &*& C_R == content(FP_R) 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /tests/spl/include/byte_array.spl: -------------------------------------------------------------------------------- 1 | predicate byte_arrayseg(a: Array, i: Int, j: Int) { 2 | 0 <= i && i <= j && j <= a.length && a.length <= 65535 &*& //FIXME hack while we improve the BV backend 3 | acc({ c: ArrayCell :: i <= c.index && c.index < j && c.array == a }) 4 | } 5 | 6 | predicate byte_array(a: Array) { 7 | acc(a) &*& byte_arrayseg(a, 0, a.length) 8 | } 9 | -------------------------------------------------------------------------------- /tests/spl/include/dllist.spl: -------------------------------------------------------------------------------- 1 | // Structure and predicate declarations for doubly-linked lists 2 | 3 | struct Node { 4 | var next: Node; 5 | var prev: Node; 6 | } 7 | 8 | predicate dlseg(x1: Node, x2: Node, y1: Node, y2: Node) { 9 | acc({ z: Node :: Btwn(next, x1, z, y1) && z != y1}) &*& 10 | (x1 == y1 && x2 == y2 || 11 | //x1 in FP && y2 in FP && 12 | x1 != x2 && y1 != y2 && 13 | Btwn (next, x1, y2, y1) && 14 | Btwn (prev, y2, x1, x2) && 15 | //y2.next == y1 && 16 | (forall l1: Node :: Btwn(next, y2, l1, y1) ==> l1 == y2 || l1 == y1) && 17 | //x1.prev == x2 && 18 | (forall l1: Node :: Btwn(prev, x1, l1, x2) ==> l1 == x1 || l1 == x2) && 19 | (forall l1: Node, l2: Node :: 20 | Btwn(next, x1, l1, y1) && Btwn(next, x1, l2, y1) && Btwn(next, l1, l2, y1) ==> 21 | l2 == y1 || Btwn(prev, y2, l2, l1) && Btwn(prev, l2, l1, x1)) && 22 | (forall l1: Node, l2: Node :: 23 | Btwn(prev, y2, l1, x2) && Btwn(prev, y2, l2, x2) && Btwn(prev, l1, l2, x2) ==> 24 | l2 == x2 || Btwn(next, x1, l2, l1) && Btwn(next, l2, l1, y1))) 25 | } 26 | -------------------------------------------------------------------------------- /tests/spl/include/node_array.spl: -------------------------------------------------------------------------------- 1 | type Node; 2 | 3 | predicate arrayseg(a: Array, i: Int, j: Int) 4 | requires acc(a) 5 | { 6 | 0 <= i && i <= j && j <= a.length &*& 7 | acc({ c: ArrayCell :: i <= c.index && c.index < j && c.array == a }) 8 | } 9 | 10 | predicate array(a: Array) { 11 | acc(a) &*& 12 | arrayseg(a, 0, a.length) 13 | } 14 | 15 | function node_witness(x: Node, FP0: Set>) 16 | returns (res: ArrayCell) 17 | requires acc(FP0) 18 | ensures forall c in FP0 :: c == node_witness(c[], FP0) 19 | 20 | function arrayseg_content(a: Array, FP0: Set>) returns (N: Set) 21 | requires acc(a) &*& acc(FP0) 22 | ensures forall c in FP0 :: c[] in N 23 | ensures forall x in N :: x == node_witness(x, FP0)[] @(matching x yields node_witness(x, FP0)[]) 24 | ensures forall x in N :: node_witness(x, FP0) in FP0 25 | ensures forall x: Node :: x !in N ==> null == node_witness(x, FP0) 26 | ensures forall FP1: Set>, n in N :: 27 | node_witness(n, FP0) in FP1 ==> node_witness(n, FP0) = node_witness(n, FP1) 28 | 29 | 30 | predicate arrayseg_with_content(a: Array, lo: Int, hi: Int, N: Set) 31 | requires acc(a) 32 | { 33 | exists X: Set> :: 34 | arrayseg(a, lo, hi) && acc(X) &*& 35 | N == arrayseg_content(a, X) 36 | } 37 | 38 | predicate array_with_content(a: Array, N: Set) { 39 | acc(a) &*& 40 | arrayseg_with_content(a, 0, a.length, N) 41 | } 42 | 43 | -------------------------------------------------------------------------------- /tests/spl/include/ordered_type.spl: -------------------------------------------------------------------------------- 1 | // An ordered type 2 | type K 3 | 4 | /* 5 | pure function compare(x: K, y: K) returns (res: Int) 6 | pure predicate lt(x: K, y: K) 7 | pure predicate le(x: K, y: K) 8 | 9 | const bot: K 10 | const top: K 11 | 12 | auto lemma bot_smallest(x: K) 13 | ensures !lt(x, bot) 14 | 15 | auto lemma top_largest(x: K) 16 | ensures !lt(top, x) 17 | 18 | auto lemma lt_irreflexive(x: K) 19 | ensures !lt(top, x) 20 | */ 21 | 22 | pure predicate lt(x: K, y: K) 23 | 24 | const bot: K 25 | const top: K 26 | 27 | axiom forall a: K :: !lt(a, bot) 28 | axiom forall a: K :: !lt(top, a) 29 | axiom bot != top 30 | 31 | axiom forall a: K :: !lt(a, a) 32 | axiom forall a: K, b: K :: !lt(a, b) || !lt(b, a) 33 | axiom forall a: K, b: K :: lt(a, b) || lt(b, a) || a == b 34 | axiom forall a: K, b: K, c: K :: lt(a, b) && lt(b, c) ==> lt(a, c) 35 | 36 | function le(x: K, y: K) returns (res: Bool) { 37 | lt(x, y) || x == y 38 | } 39 | 40 | 41 | function compare(x: K, y: K) returns (res: Int) 42 | { 43 | x == y ? 0 : (lt(x, y) ? -1 : 1) 44 | } -------------------------------------------------------------------------------- /tests/spl/include/simple_int_array.spl: -------------------------------------------------------------------------------- 1 | predicate array(a: Array) { 2 | acc(a) 3 | } 4 | 5 | function contentWitness(v: Int, a: Array) 6 | returns (res: Int) 7 | requires acc(a) 8 | ensures forall i: Int :: i == contentWitness(a[i], a) 9 | 10 | function array_content(a: Array) 11 | returns (C: Set) 12 | requires acc(a) 13 | ensures forall i: Int :: 0 <= i && i < a.length ==> a[i] in C 14 | ensures forall v in C :: 0 <= contentWitness(v, a) && contentWitness(v, a) < a.length 15 | ensures forall v in C :: v == a[contentWitness(v, a)] 16 | @(matching v yields a[contentWitness(v, a)]) 17 | 18 | predicate array_cnt(a: Array, C: Set) { 19 | acc(a) &*& C == array_content(a) 20 | } 21 | 22 | predicate is_sorted_arrayseg(a: Array, i: Int, j: Int) 23 | requires array(a) 24 | { 25 | forall i1: Int, j1: Int:: i <= i1 && i1 <= j1 && j1 < j ==> a[i1] <= a[j1] 26 | } 27 | 28 | predicate sorted_array(a: Array, C: Set) { 29 | array_cnt(a, C) &*& 30 | is_sorted_arrayseg(a, 0, a.length) 31 | } 32 | 33 | // array with bounds 34 | 35 | predicate is_bounded_arrayseg(a: Array, i: Int, j: Int, lb: Int, ub: Int) 36 | requires array(a) 37 | { 38 | forall k: Int:: i <= k && k < j ==> lb <= a[k] && a[k] < ub 39 | } 40 | 41 | predicate array_bnd(a: Array, lb: Int, ub: Int) { 42 | array(a) &*& 43 | is_bounded_arrayseg(a, 0, a.length, lb, ub) 44 | } 45 | 46 | predicate sorted_array_bnd(a: Array, lb: Int, ub: Int) { 47 | array(a) &*& 48 | is_bounded_arrayseg(a, 0, a.length, lb, ub) && 49 | is_sorted_arrayseg(a, 0, a.length) 50 | } 51 | -------------------------------------------------------------------------------- /tests/spl/include/skiplistWithLength.spl: -------------------------------------------------------------------------------- 1 | 2 | struct SkipList { 3 | var max_height: Int; 4 | var curr_height: Int; 5 | var sentinel: Node; 6 | } 7 | 8 | struct Node { 9 | var height: Int; 10 | var data: Int; 11 | var next: Node[]; 12 | var length: Int[]; 13 | } 14 | 15 | function skiplist_footprint(x: Node) returns (FP: Set>) { 16 | forall z: Loc :: z in FP == (Btwn(next[0], x, z, null) && z != null) 17 | } 18 | 19 | predicate skiplist_hierarchy(height: Int, FP: Set>) { 20 | (forall h1: Int, h2: Int :: 21 | 0 <= h1 && h1 <= h2 && h2 <= height ==> 22 | (forall x: Node, y: Node, z: Node :: 23 | x in FP && y in FP && z in FP && Btwn(next[h2], x, y, z) ==> 24 | Btwn(next[h1], x, y, z))) 25 | } 26 | 27 | predicate skiplist_strict_sorted(x: Node, FP: Set>) { 28 | forall y: Node, z: Node :: 29 | y in FP && z in FP && Btwn(next[0], x, y, z) && y != x ==> y.data < z.data 30 | } 31 | 32 | predicate skiplist_length(x: Node, FP: Set>) { 33 | (forall y: Node, z: Node, h: Int:: 34 | y in FP && z in FP && 35 | 0 <= h && h < y.height && 36 | y.next[h] == z && y != x 37 | ==> 38 | y.data + y.length[h] <= z.data) 39 | && 40 | (forall y: Node, h1: Int, h2: Int:: 41 | y in FP && 0 <= h1 && h1 <= h2 && h2 < y.height 42 | ==> 43 | y.length[h1] > 0 && 44 | y.length[h1] <= y.length[h2]) 45 | } 46 | 47 | predicate skiplist_reach_null(height: Int, x: Node) { 48 | forall h: Int :: 0 <= h && h <= height ==> Btwn(next[h], x, null, null) 49 | } 50 | 51 | predicate skiplist(l: SkipList, FP0: Set>, FP1: Set>) { 52 | 0 < l.max_height && 53 | 0 <= l.curr_height && l.curr_height < l.max_height && 54 | skiplist_reach_null(l.curr_height, l.sentinel) && 55 | skiplist_hierarchy(l.sentinel, FP1) && 56 | skiplist_strict_sorted(l.sentinel, FP1) && 57 | skiplist_length(l.sentinel, FP1) && 58 | l.sentinel.height == height && 59 | FP1 == skiplist_footprint(l.head) && 60 | FP0 == Set>(l) 61 | } 62 | 63 | -------------------------------------------------------------------------------- /tests/spl/include/sllist.spl: -------------------------------------------------------------------------------- 1 | // Structure and predicate declarations for singly-linked lists 2 | 3 | struct Node { 4 | var next: Node; 5 | } 6 | 7 | predicate lseg(x: Node, y: Node) { 8 | acc({ z: Node :: Btwn(next, x, z, y) && z != y }) &*& Reach(next, x, y) 9 | } 10 | 11 | -------------------------------------------------------------------------------- /tests/spl/include/sllist_rec.spl: -------------------------------------------------------------------------------- 1 | struct Node { 2 | var next: Node; 3 | } 4 | 5 | predicate lseg(x: Node, y: Node) { 6 | x == y || 7 | x != y &*& acc(x) &*& lseg(x.next, y) 8 | } 9 | -------------------------------------------------------------------------------- /tests/spl/include/slsset.spl: -------------------------------------------------------------------------------- 1 | // function and predicate declarations for a set implementation 2 | // based on sorted singly-linked lists 3 | 4 | include "slslist.spl"; 5 | 6 | function data_witness(v: Int, FP: Set) returns (res: Node) 7 | requires acc(FP) 8 | ensures forall x in FP :: x == data_witness(x.data, FP) 9 | 10 | function content(FP: Set) 11 | returns (C: Set) 12 | requires acc(FP) 13 | ensures forall x in FP :: x.data in C 14 | ensures forall v in C :: data_witness(v, FP) in FP 15 | ensures forall v: Int :: v !in C ==> data_witness(v, FP) == null 16 | ensures forall v in C :: v == data_witness(v, FP).data @(matching v yields data_witness(v, FP).data) 17 | ensures forall v in C, FP1: Set :: data_witness(v, FP) in FP1 ==> data_witness(v, FP) == data_witness(v, FP1) 18 | 19 | /* 20 | function content(FP: Set) 21 | returns (C: Set) 22 | requires acc(FP) 23 | { 24 | { v: Int :: exists x: Node :: x in FP && x.data == v } 25 | } 26 | */ 27 | 28 | predicate list_set(x: Node, y: Node, C: Set) { 29 | exists X: Set :: 30 | lseg(x, y) && acc(X) &*& 31 | lseg_strictly_increasing(x, X) && C == content(X) 32 | } 33 | -------------------------------------------------------------------------------- /tests/spl/include/treeset.spl: -------------------------------------------------------------------------------- 1 | include "bstree.spl"; 2 | 3 | // Predicates for tree sets 4 | 5 | function data_witness(v: Int, FP: Set) 6 | returns (res: Node) 7 | requires acc(FP) 8 | ensures forall x in FP :: x == data_witness(x.data, FP) 9 | 10 | function content(FP: Set) returns (C: Set) 11 | requires acc(FP) 12 | ensures forall v: Int :: v !in C ==> data_witness(v, FP) == null 13 | ensures forall x in FP :: x.data in content(FP) 14 | ensures forall v in C :: data_witness(v, FP) in FP; 15 | ensures forall v in C :: v == data_witness(v, FP).data 16 | @(matching v yields data_witness(v, FP).data); 17 | 18 | 19 | predicate tree_set(r: Node, C: Set) { 20 | exists X: Set :: 21 | bstree(r) && acc(X) &*& 22 | C == content(X) 23 | } 24 | 25 | predicate heap_set(r: Node, C: Set) { 26 | exists X: Set :: 27 | tree(r) && acc(X) &*& 28 | heap_property(X) && 29 | C == content(X) 30 | } 31 | -------------------------------------------------------------------------------- /tests/spl/lib_examples/consoleTest.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/console.spl"; 2 | 3 | 4 | procedure Main(arg: Array) returns (res: Int) 5 | requires byte_array(arg) 6 | ensures byte_array(arg) 7 | { 8 | var success := true; 9 | var content := new Array(14); 10 | content := "hello world!\n"; 11 | success := gputs(content); 12 | 13 | var input := new Array(128); 14 | 15 | while (ggets(input) >= 0) 16 | invariant byte_array(content) &*& content.length == 14 17 | invariant byte_array(input) 18 | { 19 | content := "you said:\n"; 20 | success := gputs(content); 21 | success := gputs(input); 22 | } 23 | 24 | free(content); 25 | free(input); 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/lib_examples/fileTest.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/file.spl"; 2 | 3 | procedure Main(arg: Array) returns (res: Int) 4 | requires byte_array(arg) 5 | ensures byte_array(arg) 6 | { 7 | if (arg.length == 0) { 8 | return 1; 9 | } 10 | var fd := gopen(arg, O_CREAT | O_WRONLY | O_TRUNC); 11 | if (fd == -1) { 12 | return 2; 13 | } 14 | 15 | var content := new Array(14); 16 | content := "hello world!\n"; 17 | 18 | if (gwrite2(fd, content, 13) != 13) { 19 | free(content); 20 | return 3; 21 | } 22 | 23 | var closed := gclose(fd); 24 | var i := 0; 25 | while (i < 13) 26 | invariant i >= 0 && i <= 13 27 | invariant byte_array(content) 28 | invariant content.length == 14 29 | { 30 | content[i] := int2byte(0); 31 | i := i + 1; 32 | } 33 | 34 | fd := gopen(arg, O_RDONLY); 35 | if (fd == -1) { 36 | free(content); 37 | return 4; 38 | } 39 | 40 | var read := gread(fd, content); 41 | if (read != 13) { 42 | free(content); 43 | return 5; 44 | } 45 | 46 | if (content[ 0] != 'h' || 47 | content[ 1] != 'e' || 48 | content[ 2] != 'l' || 49 | content[ 3] != 'l' || 50 | content[ 4] != 'o' || 51 | content[ 5] != ' ' || 52 | content[ 6] != 'w' || 53 | content[ 7] != 'o' || 54 | content[ 8] != 'r' || 55 | content[ 9] != 'l' || 56 | content[10] != 'd' || 57 | content[11] != '!' || 58 | content[12] != int2byte( 10) ) // \n 59 | { 60 | free(content); 61 | return 6; 62 | } 63 | 64 | free(content); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /tests/spl/lib_examples/socketTcpReceiver.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/socket.spl"; 2 | include "../../../lib/file.spl"; 3 | include "../../../lib/fork.spl"; 4 | 5 | procedure Main(arg: Array) returns (res: Int) 6 | requires byte_array(arg) 7 | ensures byte_array(arg) 8 | { 9 | var port := new Array(5); 10 | port := "4444"; 11 | var addr := get_address4(null, port); //null should return localhost 12 | free(port); 13 | if (addr == null) { 14 | return 1; 15 | } 16 | 17 | var fd := create_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 18 | if (fd == -1) { 19 | free(addr); 20 | return 2; 21 | } 22 | 23 | var bound := bind4(fd, addr); 24 | if (!bound) { 25 | free(addr); 26 | return 3; 27 | } 28 | 29 | var listening := glisten(fd, 10); 30 | if (!listening) { 31 | free(addr); 32 | return 4; 33 | } 34 | 35 | var connectionFd := 0; 36 | var pid := 1; 37 | 38 | while (pid == 1 && connectionFd >= 0) 39 | invariant fd >= 0 40 | invariant socket_addr_4(addr) 41 | { 42 | connectionFd := accept4(fd, addr); 43 | if (connectionFd >= 0) { 44 | pid := fork(); 45 | if (pid > 0) { 46 | var closed := gclose(connectionFd); 47 | pid := 1; 48 | } 49 | } // else: problem when accepting, exit the loop 50 | } 51 | 52 | if (connectionFd == -1) { 53 | //problem when accepting 54 | free(addr); 55 | return 5; 56 | } else { 57 | free(addr); 58 | var closed := gclose(fd); 59 | 60 | var content := new Array(128); 61 | var received := tcp_recv(connectionFd, content); 62 | while (received > 0) 63 | invariant connectionFd >= 0 64 | invariant byte_array(content) 65 | { 66 | //XXX 67 | received := tcp_recv(connectionFd, content); 68 | } 69 | 70 | closed := gclose(connectionFd); 71 | free(content); 72 | return 0; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /tests/spl/lib_examples/socketTcpSender.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/socket.spl"; 2 | include "../../../lib/file.spl"; 3 | 4 | procedure Main(arg: Array) returns (res: Int) 5 | requires byte_array(arg) 6 | ensures byte_array(arg) 7 | { 8 | var port := new Array(5); 9 | port := "4444"; 10 | var addr := get_address4(null, port); //null should return localhost 11 | free(port); 12 | if (addr == null) { 13 | return 1; 14 | } 15 | 16 | var fd := create_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 17 | if (fd==-1) { 18 | free(addr); 19 | return 2; 20 | } 21 | 22 | var sent := 0; 23 | 24 | if (connect4(fd, addr)) { 25 | 26 | var content := new Array(13); 27 | content := "hello world!"; 28 | content[12] := int2byte( 10); // \n 29 | 30 | sent := tcp_send(fd, content, 13); 31 | 32 | free(content); 33 | } 34 | 35 | var closed := gclose(fd); 36 | free(addr); 37 | 38 | if (sent != 13) { 39 | return 3; 40 | } else { 41 | return 0; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /tests/spl/lib_examples/socketUdpReceiver.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/socket.spl"; 2 | include "../../../lib/file.spl"; 3 | 4 | procedure Main(arg: Array) returns (res: Int) 5 | requires byte_array(arg) 6 | ensures byte_array(arg) 7 | { 8 | var port := new Array(5); 9 | port := "4444"; 10 | var addr := get_address4(null, port); //null should return localhost 11 | free(port); 12 | if (addr == null) { 13 | return 1; 14 | } 15 | 16 | var fd := create_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 17 | if (fd==-1) { 18 | free(addr); 19 | return 2; 20 | } 21 | 22 | var bound := bind4(fd, addr); 23 | if (!bound) { 24 | return 3; 25 | } 26 | 27 | var content := new Array(128); 28 | 29 | var received := udp_recv4(fd, content, addr); 30 | var closed := gclose(fd); 31 | 32 | free(addr); 33 | 34 | if (received != 13) { 35 | free(content); 36 | return 4; 37 | } 38 | 39 | if (content[ 0] != 'h' || 40 | content[ 1] != 'e' || 41 | content[ 2] != 'l' || 42 | content[ 3] != 'l' || 43 | content[ 4] != 'o' || 44 | content[ 5] != ' ' || 45 | content[ 6] != 'w' || 46 | content[ 7] != 'o' || 47 | content[ 8] != 'r' || 48 | content[ 9] != 'l' || 49 | content[10] != 'd' || 50 | content[11] != '!' || 51 | content[12] != int2byte( 10) ) // \n 52 | { 53 | free(content); 54 | return -6; 55 | } else { 56 | free(content); 57 | return 0; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /tests/spl/lib_examples/socketUdpSender.spl: -------------------------------------------------------------------------------- 1 | include "../../../lib/socket.spl"; 2 | include "../../../lib/file.spl"; 3 | 4 | procedure Main(arg: Array) returns (res: Int) 5 | requires byte_array(arg) 6 | ensures byte_array(arg) 7 | { 8 | var port := new Array(5); 9 | port := "4444"; 10 | var addr := get_address4(null, port); //null should return localhost 11 | free(port); 12 | if (addr == null) { 13 | return 1; 14 | } 15 | 16 | var fd := create_socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 17 | if (fd==-1) { 18 | free(addr); 19 | return 2; 20 | } 21 | 22 | var content := new Array(13); 23 | content := "hello world!"; 24 | content[12] := int2byte( 10); // \n 25 | 26 | var sent := udp_send4(fd, content, 13, addr); 27 | var closed := gclose(fd); 28 | free(addr); 29 | free(content); 30 | 31 | if (sent != 13) { 32 | return 3; 33 | } else { 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/spl/link_and_array/sllist_next_test.spl: -------------------------------------------------------------------------------- 1 | // Test to see if reachability over user defined fields works on a simple singly linked list example 2 | 3 | struct Node { 4 | var next: Node; 5 | } 6 | 7 | function next_map() returns (m: Map) { 8 | //m == next 9 | //(forall x: Node :: x.m == x.next @(matching x.next yields x.m) @(matching x.m yields x.next) @(comment "next-map")) && 10 | (forall x: Node, y: Node, z: Node :: Btwn(next, x, y, z) == Btwn(m, x, y, z)) 11 | } 12 | 13 | function lseg_footprint(x: Node, y: Node) returns (FP: Set) { 14 | forall z: Node :: z in FP == (Btwn(next_map(), x, z, y) && z != y) 15 | } 16 | 17 | predicate lseg(x: Node, y: Node)(FP: Set) { 18 | Reach(next_map(), x, y) && FP == lseg_footprint(x, y) 19 | } 20 | 21 | procedure traverse1(lst: Node) 22 | requires lseg(lst, null) 23 | ensures lseg(lst, null) 24 | { 25 | var curr := lst; 26 | while (curr != null) 27 | invariant lseg(lst, curr) 28 | invariant lseg(curr, null) 29 | { 30 | curr := curr.next; 31 | } 32 | } 33 | 34 | procedure traverse2(lst: Node) 35 | requires lseg(lst, null); 36 | ensures lseg(lst, null); 37 | { 38 | if (lst != null) { 39 | var curr := lst; 40 | while (curr.next != null) 41 | invariant lseg(lst, curr); 42 | invariant lseg(curr, null); 43 | { 44 | curr := curr.next; 45 | } 46 | } 47 | } 48 | 49 | procedure reverse(lst: Node) 50 | returns (rev: Node) 51 | requires lseg(lst, null) 52 | ensures lseg(rev, null) 53 | { 54 | rev := null; 55 | var curr := lst; 56 | while (curr != null) 57 | invariant lseg(rev, null) 58 | invariant lseg(curr, null) 59 | { 60 | var tmp := curr; 61 | curr := curr.next; 62 | tmp.next := rev; 63 | rev := tmp; 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /tests/spl/list_set/contains.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure contains(lst: Node, val: Int, implicit ghost C: Set) 6 | returns (res: Bool) 7 | requires list_set(lst, null, C) 8 | ensures (res == val in C) &*& list_set(lst, null, C) 9 | { 10 | var curr: Node; 11 | curr := lst; 12 | var prev: Node; 13 | prev := null; 14 | while (curr != null && curr.data < val) 15 | invariant (prev == null && curr == lst || val > prev.data &*& prev.next |-> curr) -** 16 | list_set(lst, null, C) 17 | { 18 | prev := curr; 19 | curr := curr.next; 20 | } 21 | if (curr != null && curr.data == val) return true; 22 | else return false; 23 | } 24 | -------------------------------------------------------------------------------- /tests/spl/list_set/delete.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure delete(lst: Node, val: Int, implicit ghost C: Set) 6 | returns (res: Node) 7 | requires list_set(lst, null, C) 8 | ensures list_set(res, null, C -- {val}) 9 | { 10 | var curr: Node, prev: Node; 11 | curr := lst; 12 | prev := null; 13 | 14 | while (curr != null && curr.data < val) 15 | invariant (prev == null && curr == lst || val > prev.data &*& prev.next |-> curr) -** 16 | list_set(lst, null, C) 17 | { 18 | prev := curr; 19 | curr := curr.next; 20 | } 21 | 22 | if (curr != null && curr.data == val) { 23 | var n: Node; 24 | n := curr; 25 | curr := curr.next; 26 | free n; 27 | if (prev != null) { 28 | prev.next := curr; 29 | return lst; 30 | } else { 31 | return curr; 32 | } 33 | } else { 34 | return lst; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/spl/list_set/difference.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure difference(lst1: Node, lst2: Node, 6 | implicit ghost C1: Set, implicit ghost C2: Set) 7 | returns (res: Node) 8 | requires list_set(lst1, null, C1) &*& list_set(lst2, null, C2); 9 | ensures list_set(lst2, null, C2) &*& list_set(res, null, C1 -- C2); 10 | { 11 | if (lst1 == null) { 12 | return lst1; 13 | } else if (lst2 == null) { 14 | return lst1; 15 | } else if (lst1.data < lst2.data) { 16 | lst1.next := difference(lst1.next, lst2); 17 | return lst1; 18 | } else if (lst1.data > lst2.data) { 19 | return difference(lst1, lst2.next); 20 | } else { //lst1.data == lst2.data 21 | var n: Node; 22 | n := lst1.next; 23 | free lst1 ; 24 | return difference(n, lst2.next); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/list_set/insert.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure append(val: Int, x: Node, implicit ghost C: Set) 6 | returns (res: Node) 7 | requires list_set(x, null, C) 8 | requires forall v in C :: val < v 9 | ensures list_set(res, null, C ++ {val}) 10 | { 11 | res := new Node; 12 | res.next := x; 13 | res.data := val; 14 | } 15 | 16 | procedure insert(lst: Node, val: Int, implicit ghost C: Set) 17 | returns (res: Node) 18 | requires list_set(lst, null, C) 19 | ensures list_set(res, null, C ++ {val}) 20 | { 21 | var curr := lst; 22 | var prev: Node := null; 23 | 24 | while (curr != null && curr.data < val) 25 | invariant (prev == null && curr == lst || val > prev.data &*& prev.next |-> curr) -** 26 | list_set(lst, null, C) 27 | { 28 | prev := curr; 29 | curr := curr.next; 30 | } 31 | 32 | if (curr != null && curr.data == val) { 33 | return lst; 34 | } 35 | 36 | var n: Node; 37 | //n := append(val, curr); 38 | n := new Node; 39 | n.next := curr; 40 | n.data := val; 41 | 42 | if (prev == null) { 43 | return n; 44 | } else { 45 | prev.next := n; 46 | return lst; 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /tests/spl/list_set/intersect.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure intersect(x: Node, y: Node, implicit ghost x_content: Set, 6 | implicit ghost y_content: Set) 7 | returns (res: Node) 8 | requires list_set(x, null, x_content) 9 | requires list_set(y, null, y_content) 10 | ensures list_set(res, null, x_content ** y_content) 11 | ensures list_set(y, null, y_content) 12 | { 13 | if (x == null || y == null) { 14 | delete(x); 15 | return null; 16 | } else if (x.data < y.data) { 17 | var tmp: Node; 18 | tmp := x.next; 19 | free x; 20 | return intersect(tmp, y); 21 | } else if (x.data > y.data) { 22 | return intersect(x, y.next); 23 | } else { 24 | x.next := intersect(x.next, y.next); 25 | return x; 26 | } 27 | } 28 | 29 | procedure delete(x: Node) 30 | requires lseg(x, null) 31 | ensures emp 32 | { 33 | if (x == null) return; 34 | var tmp: Node; 35 | tmp := x.next; 36 | free x; 37 | delete(tmp); 38 | } 39 | -------------------------------------------------------------------------------- /tests/spl/list_set/split.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | predicate ls_unord(x: Node, y: Node, C: Set) { 4 | exists X: Set :: 5 | lseg(x, y) && acc(X) &*& C == content(X) 6 | } 7 | 8 | procedure split(x: Node, y: Node, implicit ghost C: Set) 9 | returns (t: Node) 10 | requires ls_unord(x, y, C)// &*& x != y 11 | ensures exists C1: Set, C2: Set :: 12 | ls_unord(x, t, C1) &*& ls_unord(t, y, C2) &*& C == C1 ++ C2 13 | { 14 | t := x; 15 | var nondet: Bool; 16 | while (nondet && t != y) 17 | invariant exists C1: Set, C2: Set :: 18 | //ls_unord(x, t, C1) &*& ls_unord(t, y, C2) &*& C == C1 ++ C2 19 | ls_unord(x, t, C1) &*& ls_unord(t, y, C2) -** ls_unord(x, y, C) 20 | { 21 | havoc nondet; 22 | t := t.next; 23 | } 24 | return t; 25 | } 26 | -------------------------------------------------------------------------------- /tests/spl/list_set/traverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure traverse(lst: Node, implicit ghost C: Set) 6 | requires list_set(lst, null, C) 7 | ensures list_set(lst, null, C) 8 | { 9 | var curr: Node; 10 | curr := lst; 11 | var prev: Node; 12 | prev := null; 13 | while (curr != null) 14 | invariant (prev == null && curr == lst || prev.next |-> curr) -** 15 | list_set(lst, null, C) 16 | { 17 | prev := curr; 18 | curr := curr.next; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/list_set/union.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | options "-stratify" 4 | 5 | procedure union(lst1: Node, lst2: Node, 6 | implicit ghost C1: Set, implicit ghost C2: Set) 7 | returns (res: Node) 8 | requires list_set(lst1, null, C1) &*& list_set(lst2, null, C2); 9 | ensures list_set(res, null, C1 ++ C2); 10 | { 11 | if (lst1 == null) { 12 | return lst2; 13 | } else if (lst2 == null) { 14 | return lst1; 15 | } else if (lst1.data < lst2.data) { 16 | lst1.next := union(lst1.next, lst2); 17 | return lst1; 18 | } else if (lst1.data > lst2.data) { 19 | lst2.next := union(lst1, lst2.next); 20 | return lst2; 21 | } else { //lst1.data == lst2.data 22 | var n: Node; 23 | n := lst1.next; 24 | free(lst1); 25 | return union(n, lst2); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/spl/multi_copy/ordered_type.spl: -------------------------------------------------------------------------------- 1 | // An ordered type 2 | type K 3 | 4 | pure predicate lt(x: K, y: K) 5 | 6 | const bottom: K 7 | const top: K 8 | 9 | axiom forall a: K :: !lt(a, bottom) 10 | axiom forall a: K :: !lt(top, a) 11 | axiom bottom != top 12 | 13 | axiom forall a: K :: !lt(a, a) 14 | axiom forall a: K, b: K :: !lt(a, b) || !lt(b, a) 15 | axiom forall a: K, b: K :: lt(a, b) || lt(b, a) || a == b 16 | axiom forall a: K, b: K, c: K :: lt(a, b) && lt(b, c) ==> lt(a, c) 17 | 18 | function le(x: K, y: K) returns (res: Bool) { 19 | lt(x, y) || x == y 20 | } 21 | 22 | function compare(x: K, y: K) returns (res: Int) 23 | { 24 | x == y ? 0 : (lt(x, y) ? -1 : 1) 25 | } 26 | 27 | function increment(x: K) returns (res: K) 28 | ensures lt(x, res) -------------------------------------------------------------------------------- /tests/spl/nested_sl/create.spl: -------------------------------------------------------------------------------- 1 | include "nested_def.spl"; 2 | 3 | procedure create() returns (x: OuterNode) 4 | requires emp 5 | ensures nlseg(x, null) 6 | { 7 | x := new OuterNode(); 8 | var y := new InnerNode(); 9 | var z := new InnerNode(); 10 | 11 | x.onext := null; 12 | y.head := x; 13 | x.down := y; 14 | y.inext := z; 15 | z.head := x; 16 | z.inext := null; 17 | } 18 | -------------------------------------------------------------------------------- /tests/spl/nested_sl/destroy.spl: -------------------------------------------------------------------------------- 1 | include "nested_def.spl"; 2 | 3 | procedure destroy(x: OuterNode, y: OuterNode) 4 | requires nlseg(x, y) 5 | ensures emp 6 | { 7 | var oc := x; 8 | while (oc != y) 9 | invariant nlseg(oc, y) 10 | { 11 | var ic := oc.down; 12 | while (ic != null) 13 | invariant lseg(ic, null) 14 | { 15 | var i := ic; 16 | ic := ic.inext; 17 | free(i); 18 | } 19 | x := oc; 20 | oc := oc.onext; 21 | free(x); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/spl/nested_sl/insert.spl: -------------------------------------------------------------------------------- 1 | include "nested_def.spl"; 2 | 3 | 4 | procedure insert(x: OuterNode) returns (res: OuterNode) 5 | requires nlseg(x, null) 6 | ensures nlseg(res, null) 7 | { 8 | if (x == null) { 9 | var o := new OuterNode; 10 | o.onext := null; 11 | var i := new InnerNode; 12 | o.down := i; 13 | i.head := o; 14 | i.inext := null; 15 | return o; 16 | } else { 17 | var nondet: Bool; 18 | var curr := x; 19 | //traverse outer list 20 | while (nondet && curr.onext != null) 21 | invariant acc(curr) -** nlseg(x, null) 22 | { 23 | havoc nondet; 24 | curr := curr.onext; 25 | } 26 | //new outer node 27 | if (nondet && curr.onext == null) { 28 | var o := new OuterNode; 29 | o.onext := null; 30 | o.down := null; 31 | curr.onext := o; 32 | curr := o; 33 | } else { 34 | assume false; 35 | } 36 | //insert in inner list 37 | if (curr.down == null) { 38 | var i := new InnerNode; 39 | curr.down := i; 40 | i.head := curr; 41 | i.inext := null; 42 | return x; 43 | } else { 44 | assume false; 45 | havoc nondet; 46 | var icurr := curr.down; 47 | //traverse the inner list 48 | while(nondet && icurr.inext != null) 49 | invariant acc(icurr) -** lseg(curr.down, null) 50 | { 51 | havoc nondet; 52 | icurr := icurr.inext; 53 | } 54 | var i := new InnerNode; 55 | i.inext := icurr.inext; 56 | icurr.inext := i; 57 | i.head := curr; 58 | return x; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /tests/spl/nested_sl/nested_def.spl: -------------------------------------------------------------------------------- 1 | // Structure and predicate declarations for nested lists with head pointers 2 | 3 | struct OuterNode { 4 | var onext: OuterNode; 5 | var down: InnerNode; 6 | } 7 | 8 | struct InnerNode { 9 | var inext: InnerNode; 10 | var head: OuterNode; 11 | } 12 | 13 | predicate lseg(x: InnerNode, y: InnerNode) { 14 | Reach(inext, x, y) &*& 15 | acc({ z: InnerNode :: Btwn(inext, x, z, y) && z != y }) 16 | } 17 | 18 | function nlseg_inner_footprint(x: OuterNode, y: OuterNode, X: Set) 19 | returns (FP: Set) 20 | requires olseg(x, y) && acc(X) 21 | ensures forall z in FP :: z.head in X 22 | ensures forall z in FP, zh: OuterNode :: zh == z.head ==> 23 | /* z in lseg_footprint(zh.down, null) */ 24 | Btwn(inext, zh.down, z, null) && z != null 25 | @(matching z yields z.head.down) 26 | @(matching zh yields zh.down.head) 27 | ensures forall zh in X, z: InnerNode :: Btwn(inext, zh.down, z, null) && z != null ==> z in FP 28 | 29 | 30 | predicate olseg(x: OuterNode, y: OuterNode) { 31 | Reach(onext, x, y) &*& 32 | acc({ z: OuterNode :: Btwn(onext, x, z, y) && z != y }) 33 | } 34 | 35 | predicate nlseg(x: OuterNode, y: OuterNode) { 36 | exists X: Set :: 37 | olseg(x, y) && acc(X) &*& 38 | acc(nlseg_inner_footprint(x, y, X)) &*& 39 | (forall u in X, v in nlseg_inner_footprint(x, y, X) :: Reach(inext, u.down, v) ==> v.head == u) && 40 | (forall u in X :: Reach(inext, u.down, null)) 41 | } 42 | -------------------------------------------------------------------------------- /tests/spl/nested_sl/nested_def2.spl: -------------------------------------------------------------------------------- 1 | // Structure and predicate declarations for nested lists with head pointers 2 | 3 | struct OuterNode { 4 | var onext: OuterNode; 5 | var down: InnerNode; 6 | } 7 | 8 | struct InnerNode { 9 | var inext: InnerNode; 10 | var head: OuterNode; 11 | } 12 | 13 | function lseg_footprint(x: InnerNode, y: InnerNode) 14 | returns (FP: Set>) 15 | { 16 | forall z: Loc :: z in FP == (Btwn(inext, x, z, y) && z != y && z in InnerNode) 17 | } 18 | 19 | predicate lseg(x: InnerNode, y: InnerNode, FP: Set>) { 20 | Reach(inext, x, y) && 21 | FP == lseg_footprint(x, y) 22 | } 23 | 24 | function nlseg_outer_footprint(x: OuterNode, y: OuterNode) 25 | returns (FP: Set>) 26 | { 27 | forall z: Loc :: z in FP == (Btwn(onext, x, z, y) && z != y && z in OuterNode) 28 | } 29 | 30 | function dinext() returns(m: Map, Loc>) { 31 | forall x: Loc, y: Loc :: x.m == y == (x.down == y || x.inext == y) 32 | @(matching x.down yields m[x]) 33 | @(matching x.inext yields m[x]) 34 | } 35 | 36 | function nlseg_inner_footprint(x: OuterNode, y: OuterNode) 37 | returns (FP: Set>) 38 | { 39 | (forall z: Loc :: z in FP ==> 40 | z.head in nlseg_outer_footprint(x, y)) && 41 | (forall z: Loc, zh: Loc :: z in FP && zh == z.head ==> 42 | /* z in lseg_footprint(zh.down, null) */ 43 | Btwn(inext, zh.down, z, null) && z != null 44 | @(matching z yields z.head) 45 | @(matching zh yields zh.down)) && 46 | (forall zh: Loc, z: Loc :: 47 | zh in nlseg_outer_footprint(x, y) && 48 | /*z in lseg_footprint(zh.down, null)*/ 49 | Btwn(inext, zh.down, z, null) && z != null ==> z in FP) 50 | } 51 | 52 | predicate nlseg(x: OuterNode, y: OuterNode, FP0: Set>, FP1: Set>) { 53 | Reach(onext, x, y) && 54 | (forall u: OuterNode, v: InnerNode :: 55 | u in nlseg_outer_footprint(x, y) && v in nlseg_inner_footprint(x, y) && 56 | Reach(inext, u.down, v) ==> v.head == u) && 57 | (forall u: OuterNode :: u in nlseg_outer_footprint(x, y) ==> Reach(inext, u.down, null)) && 58 | FP0 == nlseg_outer_footprint(x, y) && 59 | FP1 == nlseg_inner_footprint(x, y) 60 | } 61 | -------------------------------------------------------------------------------- /tests/spl/nested_sl/remove.spl: -------------------------------------------------------------------------------- 1 | include "nested_def.spl"; 2 | 3 | 4 | procedure remove(x: OuterNode) returns (res: OuterNode) 5 | requires nlseg(x, null) 6 | ensures nlseg(res, null) 7 | { 8 | if (x == null) 9 | return null; 10 | else { 11 | var nondet: Bool; 12 | var curr := x; 13 | //traverse outer list 14 | while (nondet && curr.onext != null) 15 | invariant acc(curr) -** nlseg(x, null) 16 | { 17 | havoc nondet; 18 | curr := curr.onext; 19 | } 20 | var prev := curr; 21 | curr := curr.onext; 22 | if (curr != null) { 23 | //traverse inner list 24 | if (curr.down != null) { 25 | havoc nondet; 26 | var icurr := curr.down; 27 | //traverse the inner list 28 | while(nondet && icurr.inext != null) 29 | invariant acc(icurr) -** lseg(curr.down, null) 30 | { 31 | havoc nondet; 32 | icurr := icurr.inext; 33 | } 34 | if (!nondet && icurr.inext == null && curr.down == icurr) { 35 | curr.down := null; 36 | free(icurr); 37 | } else { 38 | var iprev := icurr; 39 | icurr := icurr.inext; 40 | if (icurr != null) { 41 | iprev.inext := icurr.inext; 42 | free(icurr); 43 | } 44 | } 45 | } 46 | if (curr.down == null) { 47 | prev.onext := curr.onext; 48 | free(curr); 49 | } 50 | } 51 | return x; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/spl/nested_sl/traverse.spl: -------------------------------------------------------------------------------- 1 | include "nested_def.spl"; 2 | 3 | procedure traverse(x: OuterNode, y: OuterNode) 4 | requires nlseg(x, y) 5 | ensures nlseg(x, y) 6 | { 7 | var oc := x; 8 | while (oc != y) 9 | invariant (oc == y || acc(oc)) -** nlseg(x, y) 10 | { 11 | var ic := oc.down; 12 | while (ic != null) 13 | invariant acc(oc) 14 | invariant (ic == null || acc(ic)) -** lseg(oc.down, null) 15 | { 16 | ic := ic.inext; 17 | } 18 | oc := oc.onext; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/recursive_defs/list_length.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | function lengthNodes(this: Node, end: Node) returns (l: Int) 4 | requires lseg(this, end) 5 | ensures this == end ==> l == 0 // then-branch 6 | ensures this != end ==> l == 1 + lengthNodes(this.next, end) // else-branch 7 | 8 | 9 | procedure test(x: Node) 10 | requires lseg(x, null) &*& lengthNodes(x, null) > 0 11 | ensures lseg(x, null) 12 | { 13 | pure assert x != null; 14 | } 15 | -------------------------------------------------------------------------------- /tests/spl/reloc/sls.spl: -------------------------------------------------------------------------------- 1 | include "../include/flows.spl"; 2 | 3 | /** Flow domain definitions */ 4 | 5 | datatype FlowDom = pair(fst: Int, snd: Int); 6 | 7 | pure predicate domEq(p1: FlowDom, p2: FlowDom) { 8 | p1.fst == p2.fst && p1.snd == p2.snd 9 | } 10 | 11 | pure predicate domLeq(p1: FlowDom, p2: FlowDom) { 12 | p1.fst <= p2.snd && p1.snd <= p2.snd 13 | } 14 | 15 | pure function domPlus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 16 | { pair(p1.fst + p2.fst, p1.snd + p2.snd) } 17 | 18 | pure function domMult(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 19 | { pair(p1.fst * p2.fst, p1.snd * p2.snd) } 20 | 21 | pure function domZero() returns(p: FlowDom) { pair(0, 0) } 22 | 23 | datatype NodeDom = nd; 24 | 25 | pure predicate ndLeq(a1: NodeDom, a2: NodeDom) 26 | 27 | struct Node { 28 | var next: Node; 29 | var data: Int; 30 | } 31 | 32 | define unchanged(x) { x.next == old(x.next) && x.data == old(x.data) } 33 | 34 | /** Definition of good condition, gamma */ 35 | 36 | define gammaSpatial(x) { acc(x) } 37 | 38 | define gamma(x, I) { 39 | gammaSpatial(x) &*& I.inf[x].fst == 1 &*& I.inf[x].snd < x.data 40 | &*& (x.next == null && I.FPo == {} 41 | || x.next != null && I.FPo == {x.next} && I.fm[x][x.next] == pair(1, x.data)) 42 | } 43 | 44 | /** Lemmas */ 45 | 46 | procedure no_op(x: Node, I: Interface) 47 | requires N(x, I) &*& intValid(I) == true 48 | ensures N(x, I) 49 | { 50 | lemma_conc(x, I); 51 | var y := x.next; 52 | x.next := y; 53 | lemma_abs(x, I, I); 54 | sync(I, I); 55 | } 56 | -------------------------------------------------------------------------------- /tests/spl/reloc/test_soundness1.spl: -------------------------------------------------------------------------------- 1 | include "../include/flows.spl"; 2 | 3 | /** Flow domain definitions */ 4 | 5 | datatype FlowDom = fd(pc: Int); 6 | 7 | datatype NodeDom = nd; 8 | 9 | function domPlus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 10 | { fd(p1.pc + p2.pc) } 11 | 12 | function domMult(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 13 | { fd(p1.pc * p2.pc) } 14 | 15 | function domZero() returns(p: FlowDom) { fd(0) } 16 | 17 | struct Node { 18 | var next: Node; 19 | } 20 | 21 | 22 | // Expect this to fail 23 | procedure test_valid2(I: Interface, x: Node) 24 | requires I == intUndef && I.FP == {x} && I.FPo == {} && (forall n: Node, o: Node :: I.inf[n] == fd(0) && I.fm[n][o] == fd(0)) 25 | ensures intValid(I) == true 26 | { 27 | lemma_int_valid_fold(I); 28 | } 29 | -------------------------------------------------------------------------------- /tests/spl/reloc/tests.spl: -------------------------------------------------------------------------------- 1 | include "../include/flows.spl"; 2 | 3 | /** Flow domain definitions */ 4 | 5 | datatype FlowDom = fd(pc: Int); 6 | 7 | pure predicate domEq(p1: FlowDom, p2: FlowDom) { 8 | p1.pc == p2.pc 9 | } 10 | 11 | pure predicate domLeq(p1: FlowDom, p2: FlowDom) { 12 | p1.pc <= p2.pc 13 | } 14 | 15 | pure function domPlus(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 16 | { fd(p1.pc + p2.pc) } 17 | 18 | pure function domMult(p1: FlowDom, p2: FlowDom) returns (p: FlowDom) 19 | { fd(p1.pc * p2.pc) } 20 | 21 | pure function domZero() returns(p: FlowDom) { fd(0) } 22 | 23 | datatype NodeDom = nd; 24 | 25 | pure predicate ndLeq(a1: NodeDom, a2: NodeDom) 26 | 27 | struct Node { 28 | var next: Node; 29 | } 30 | 31 | define unchanged(x) { x.next == old(x.next) } 32 | 33 | define gammaSpatial(x) { true } 34 | 35 | define gamma(x, I) { true } 36 | 37 | procedure test_valid1(I1: Interface, I2: Interface) 38 | requires ! intValid(I1) && intValid(intComp(I1, I2)) 39 | ensures false 40 | {} 41 | 42 | procedure test_decomp(x: Node, I: Interface) 43 | returns (I1: Interface, I2: Interface) 44 | requires Gr(I) &*& x in I.FP 45 | requires intValid(I) == true 46 | ensures N(x, I1) &*& Gr(I2) 47 | ensures intValid(I1) == true && intValid(I2) == true 48 | { 49 | I1, I2 := lemma_decomp(x, I); 50 | } 51 | 52 | procedure test_return1(x: Int, y: Int) returns (z: Int) 53 | requires x < 3 && y >= 4 54 | ensures x < z && z < y 55 | { 56 | return 3; 57 | } 58 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/clear.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | procedure clear(lst: Node) 4 | requires slist(lst) 5 | ensures slist(lst) &*& lst.next == null 6 | { 7 | var curr := lst.next; 8 | lst.next := null; 9 | while (curr != null) 10 | invariant lseg(curr, null) 11 | { 12 | var prev := curr; 13 | curr := curr.next; 14 | free(prev); 15 | } 16 | } 17 | 18 | procedure dispose(lst: Node) 19 | requires slist(lst) 20 | ensures emp 21 | { 22 | while (lst != null) 23 | invariant lseg(lst, null) 24 | { 25 | var curr := lst; 26 | lst := lst.next; 27 | free(curr); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/concat.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | procedure concat(a: Node, b: Node) 4 | returns (res: Node) 5 | requires slist(a) &*& slist(b) 6 | ensures slist(res) 7 | { 8 | if (a.next == null) { 9 | free(a); 10 | return b; 11 | } else { 12 | var curr := a.next; 13 | while (curr.next != null) 14 | invariant acc(curr) -** lseg(a.next, null) 15 | { 16 | curr := curr.next; 17 | } 18 | curr.next := b.next; 19 | free(b); 20 | return a; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/copy.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | procedure copy(lst: Node) returns (res: Node) 4 | requires slist(lst) 5 | ensures slist(lst) &*& slist(res) 6 | { 7 | var curr := lst.next; 8 | var cp := new Node; 9 | cp.next := null; 10 | var last := cp; 11 | while (curr != null) 12 | invariant acc(lst) 13 | invariant (curr == null || acc(curr)) -** lseg(lst.next, null) 14 | invariant lseg(cp,last) &*& last.next |-> null 15 | { 16 | last.next := new Node; 17 | last := last.next; 18 | last.next := null; 19 | curr := curr.next; 20 | } 21 | return cp; 22 | } 23 | 24 | /* 25 | procedure copy_strange(lst: Node) returns (res: Node) 26 | requires slist(lst) 27 | ensures slist(lst) &*& slist(res) 28 | { 29 | var curr := lst.next; 30 | var cp := new Node; 31 | cp.next := null; 32 | var last := cp; 33 | while (curr != null) 34 | invariant (curr == null || acc(curr)) -** lseg(lst.next, null) 35 | invariant lseg(cp,last) &*& last.next |-> null 36 | { 37 | last.next := new Node; 38 | last := last.next; 39 | last.next := null; 40 | curr := curr.next; 41 | } 42 | return cp; 43 | } 44 | */ 45 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/filter.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | procedure filter(lst: Node) 4 | requires slist(lst) 5 | ensures slist(lst) 6 | { 7 | var prv: Node, curr := lst, lst.next; 8 | while (curr != null) 9 | invariant (prv.next |-> curr) -** slist(lst); 10 | { 11 | var old_curr := curr; 12 | curr := curr.next; 13 | var nondet: Bool; 14 | if (nondet) { 15 | prv.next := old_curr.next; 16 | free old_curr; 17 | } else { 18 | prv := old_curr; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/insert.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | procedure insert(lst: Node, elt: Node) 4 | requires slist(lst) &*& elt.next |-> null 5 | ensures slist(lst) 6 | { 7 | var nondet: Bool; 8 | var curr := lst.next; 9 | if (curr == null) { 10 | lst.next := elt; 11 | } else { 12 | while (nondet && curr.next != null) 13 | invariant acc(curr) -** lseg(lst.next, null) 14 | { 15 | havoc nondet; 16 | curr := curr.next; 17 | } 18 | elt.next := curr.next; 19 | curr.next := elt; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/remove.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | 4 | procedure remove(lst: Node) 5 | requires slist(lst) 6 | ensures slist(lst) 7 | { 8 | if (lst.next != null) { 9 | var nondet: Bool; 10 | var curr := lst.next; 11 | while (nondet && curr.next != null) 12 | invariant curr != null 13 | invariant lseg(lst, curr) 14 | invariant lseg(curr, null) 15 | { 16 | havoc nondet; 17 | curr := curr.next; 18 | } 19 | 20 | var tmp := curr.next; 21 | if (tmp != null) { 22 | curr.next := tmp.next; 23 | free(tmp); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/reverse.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | procedure reverse(lst: Node) 4 | requires slist(lst) 5 | ensures slist(lst) 6 | { 7 | var rev: Node := null; 8 | var curr := lst.next; 9 | while (curr != null) 10 | invariant lseg(rev, null) 11 | invariant lseg(curr, null) 12 | { 13 | var tmp := curr; 14 | curr := curr.next; 15 | tmp.next := rev; 16 | rev := tmp; 17 | } 18 | lst.next := rev; 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/ssllist.spl: -------------------------------------------------------------------------------- 1 | // Structure and predicate declarations for singly-linked lists 2 | 3 | struct Node { 4 | var next: Node; 5 | } 6 | 7 | function lseg_footprint(x: Node, y: Node) returns (FP: Set) { 8 | forall z: Node :: z in FP == (Btwn(next, x, z, y) && z != y) 9 | } 10 | 11 | predicate lseg(x: Node, y: Node)(FP: Set) { 12 | Reach(next, x, y) && FP == lseg_footprint(x, y) 13 | } 14 | 15 | predicate slist(x: Node)(FP: Set) { 16 | Reach(next, x, null) && x != null && FP == lseg_footprint(x, null) 17 | } 18 | -------------------------------------------------------------------------------- /tests/spl/sentinel_sl/traverse.spl: -------------------------------------------------------------------------------- 1 | include "ssllist.spl"; 2 | 3 | procedure traverse(lst: Node) 4 | requires slist(lst) 5 | ensures slist(lst) 6 | { 7 | var curr := lst.next; 8 | while (curr != null) 9 | invariant lseg(lst, curr) 10 | invariant lseg(curr, null) 11 | { 12 | curr := curr.next; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/spl/simple_arrays/bubble.spl: -------------------------------------------------------------------------------- 1 | include "../include/simple_int_array.spl"; 2 | 3 | 4 | /* One pass of bubble sort should leave the maximum element in the correct position */ 5 | procedure bubble_one_pass(a: Array, high: Int, ghost lb: Int, ghost ub: Int) 6 | requires acc(a) &*& is_bounded_arrayseg(a, 0, high, lb, ub) 7 | requires high >= 0 && high <= a.length 8 | ensures acc(a) &*& is_bounded_arrayseg(a, 0, high, lb, ub) 9 | ensures forall j: Int :: 0 <= j && j < high ==> a[j] <= a[high-1] 10 | ensures forall j: Int :: high <= j && j < a.length ==> a[j] == old(a[j]) 11 | { 12 | if (high == 0 || high == 1) 13 | { 14 | return; 15 | } 16 | var i := 1; 17 | 18 | while (i < high) 19 | invariant 1 <= i && i <= high && high <= a.length 20 | invariant acc(a) &*& is_bounded_arrayseg(a, 0, high, lb, ub) 21 | invariant forall j: Int :: 0 <= j && j < i ==> a[j] <= a[i-1] 22 | invariant forall j: Int :: i <= j && j < a.length ==> a[j] == old(a[j]) 23 | { 24 | if (a[i] < a[i - 1]) 25 | { 26 | var x := a[i]; 27 | a[i] := a[i - 1]; 28 | a[i - 1] := x; 29 | } 30 | i := i + 1; 31 | } 32 | } 33 | 34 | 35 | procedure bubble_sort(a: Array, implicit ghost content: Set, implicit ghost lb: Int, implicit ghost ub: Int) 36 | requires array_bnd(a, lb, ub) 37 | ensures sorted_array_bnd(a, lb, ub) 38 | { 39 | var high := a.length; 40 | 41 | while (high > 0) 42 | invariant acc(a) 43 | invariant (high == a.length &*& is_bounded_arrayseg(a, 0, high, lb, ub)) || 44 | (high < a.length &*& a[high] >= lb &*& is_bounded_arrayseg(a, 0, high, lb, a[high]+1)) 45 | invariant is_sorted_arrayseg(a, high, a.length) 46 | invariant is_bounded_arrayseg(a, high, a.length, a[high], ub) 47 | invariant 0 <= high && high <= a.length 48 | { 49 | if (high == a.length) 50 | { 51 | bubble_one_pass(a, high, lb, ub); 52 | } 53 | else 54 | { 55 | pure assert high < a.length; 56 | bubble_one_pass(a, high, lb, a[high]+1); 57 | } 58 | high := high - 1; 59 | } 60 | return; 61 | } 62 | -------------------------------------------------------------------------------- /tests/spl/simple_arrays/copy.spl: -------------------------------------------------------------------------------- 1 | include "../include/simple_int_array.spl"; 2 | 3 | procedure copy(a: Array) 4 | returns (b: Array) 5 | requires array(a) 6 | ensures array(a) &*& array(b) 7 | ensures a.length == b.length 8 | ensures forall i: Int :: 0 <= i < a.length ==> a[i] == b[i] 9 | { 10 | b := new Array(a.length); 11 | 12 | var i := 0; 13 | 14 | while (i < a.length) 15 | invariant 0 <= i <= a.length && a.length == b.length 16 | invariant array(a) &*& array(b) 17 | invariant forall j: Int :: 0 <= j < i ==> a[j] == b[j] 18 | { 19 | b[i] := a[i]; 20 | i := i + 1; 21 | } 22 | 23 | return b; 24 | } 25 | -------------------------------------------------------------------------------- /tests/spl/simple_arrays/free.spl: -------------------------------------------------------------------------------- 1 | include "../include/simple_int_array.spl"; 2 | 3 | procedure free_array(a: Array) 4 | requires array(a) 5 | ensures emp 6 | { 7 | free a; 8 | } 9 | -------------------------------------------------------------------------------- /tests/spl/simple_arrays/initialize.spl: -------------------------------------------------------------------------------- 1 | //include "../include/simple_int_array.spl"; 2 | 3 | procedure initialize() 4 | returns (a: Array) 5 | requires emp 6 | ensures acc(a) 7 | ensures forall k: Int :: 0 <= k && k < a.length ==> a[k] == k 8 | { 9 | a := new Array(10); 10 | 11 | var i := 0; 12 | 13 | while (i < a.length) 14 | invariant i >= 0 15 | invariant acc(a) 16 | invariant forall k: Int :: 0 <= k && k < i ==> a[k] == k 17 | { 18 | a[i] := i; 19 | i := i + 1; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/spl/sl/fpcheck.spl: -------------------------------------------------------------------------------- 1 | struct Node { 2 | var next: Node; 3 | } 4 | 5 | function lseg_footprint(x: Node, y: Node) returns (X: Set) 6 | ensures forall z: Node :: z in X == (Btwn(next, x, z, y) && z != y) 7 | 8 | procedure test1(x: Node, y: Node, X: Set, Y: Set) 9 | requires acc(X) &*& acc(Y) 10 | { 11 | pure assume Reach(next, x, y); // fails without 12 | pure assume Y == lseg_footprint(x, y); 13 | havoc_all_but(X); 14 | pure assert Y == lseg_footprint(x, y); 15 | assume false; 16 | } 17 | 18 | function ok(x: Node) returns (X: Set) 19 | ensures forall z: Node :: z in X == (z == x || z == x.next) 20 | 21 | 22 | procedure test2(x: Node, X: Set, Y: Set) 23 | requires acc(X) &*& acc(Y) 24 | { 25 | pure assume Y == ok(x); 26 | havoc_all_but(X); 27 | pure assert Y == ok(x); 28 | assume false; 29 | } 30 | 31 | function bad() returns (X: Set) 32 | ensures forall x: Node :: x in X == (x != null && x.next == null) 33 | 34 | 35 | procedure test3(X: Set, Y: Set) 36 | requires acc(X) &*& acc(Y) 37 | { 38 | pure assume Y == bad(); 39 | havoc_all_but(X); 40 | pure assert Y == bad(); 41 | assume false; 42 | } 43 | 44 | procedure havoc_all_but(X: Set) 45 | requires acc(X) 46 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_concat.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure find_last(a: Node) returns (l: Node) 4 | requires a != null &*& lseg(a, null) 5 | ensures lseg(a, l) &*& l.next |-> null 6 | { 7 | var n := a.next; 8 | if (n != null) { 9 | var n2 := find_last(n); 10 | return n2; 11 | } else { 12 | return a; 13 | } 14 | } 15 | 16 | procedure rec_concat(a: Node, b: Node) 17 | requires a != null &*& lseg(a, null) &*& lseg(b, null) 18 | ensures lseg(a, null) 19 | { 20 | var l := find_last(a); 21 | l.next := b; 22 | } 23 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_copy.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure rec_reverse_loop(lst: Node, acc: Node) 4 | returns (res: Node) 5 | requires lseg(lst, null) &*& lseg(acc, null) 6 | ensures lseg(res, null) 7 | { 8 | if (lst == null) { 9 | return acc; 10 | } else { 11 | var old_lst := lst; 12 | lst := lst.next; 13 | old_lst.next := acc; 14 | return rec_reverse_loop(lst, old_lst); 15 | } 16 | } 17 | 18 | procedure rec_reverse(lst: Node) 19 | returns (res: Node) 20 | requires lseg(lst, null) 21 | ensures lseg(res, null) 22 | { 23 | return rec_reverse_loop(lst, null); 24 | } 25 | 26 | 27 | procedure rec_copy_loop(curr: Node, cp: Node) 28 | returns (res: Node) 29 | requires lseg(cp, null) &*& lseg(curr, null) 30 | ensures lseg(res, null) &*& lseg(curr, null) 31 | { 32 | if (curr == null) { 33 | return rec_reverse(cp); 34 | } else { 35 | var old_cp := cp; 36 | cp := new Node; 37 | cp.next := old_cp; 38 | var n := curr.next; 39 | return rec_copy_loop(n, cp); 40 | } 41 | } 42 | 43 | procedure rec_copy(lst: Node) 44 | returns (res: Node) 45 | requires lseg(lst, null) 46 | ensures lseg(lst, null) &*& lseg(res, null) 47 | { 48 | return rec_copy_loop(lst, null); 49 | } 50 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_dispose.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure rec_dispose(lst: Node) 4 | requires lseg(lst, null) 5 | ensures emp 6 | { 7 | if (lst != null) { 8 | var n := lst.next; 9 | free(lst); 10 | rec_dispose(n); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_filter.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure rec_filter(x: Node) returns (res: Node) 4 | requires lseg(x, null) 5 | ensures lseg(res, null) 6 | { 7 | var n1: Node, n2: Node; 8 | var nondet: Bool; 9 | if (x == null) return x; 10 | else if (nondet) { 11 | n1 := x.next; 12 | n2 := rec_filter(n1); 13 | x.next := n2; 14 | return x; 15 | } else { 16 | n1 := x.next; 17 | free(x); 18 | return rec_filter(n1); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_insert.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure rec_insert(lst: Node, elt: Node) 4 | returns (res: Node) 5 | requires lseg(lst, null) &*& elt.next |-> null 6 | ensures lseg(res, null) 7 | { 8 | if (lst == null) 9 | return elt; 10 | else { 11 | var nondet: Bool; 12 | if (nondet) { 13 | elt.next := lst; 14 | return elt; 15 | } else { 16 | var n1 := lst.next; 17 | var n2 := rec_insert(n1, elt); 18 | lst.next := n2; 19 | return lst; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_remove.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure rec_remove(lst: Node) 4 | returns (res: Node) 5 | requires lseg(lst, null) 6 | ensures lseg(res, null) 7 | { 8 | var nondet: Bool; 9 | if (lst == null) 10 | return null; 11 | else if (nondet) { 12 | var n: Node; 13 | n := lst.next; 14 | free(lst); 15 | return n; 16 | } else { 17 | var n1 := lst.next; 18 | var n2 := rec_remove(n1); 19 | lst.next := n2; 20 | return lst; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_reverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure rec_reverse_acc(curr: Node, rev: Node) 4 | returns (res: Node) 5 | requires lseg(rev, null) &*& lseg(curr, null) 6 | ensures lseg(res, null) 7 | { 8 | if (curr == null) { 9 | return rev; 10 | } else { 11 | var tmp := curr.next; 12 | curr.next := rev; 13 | return rec_reverse_acc(curr, tmp); 14 | } 15 | } 16 | 17 | procedure rec_reverse(lst: Node) 18 | returns (res: Node) 19 | requires lseg(lst, null) 20 | ensures lseg(res, null) 21 | { 22 | return rec_reverse_acc(lst, null); 23 | } 24 | -------------------------------------------------------------------------------- /tests/spl/sl/rec_traverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure rec_traverse(lst: Node) 4 | requires lseg(lst, null) 5 | ensures lseg(lst, null) 6 | { 7 | if (lst != null) { 8 | var n := lst.next; 9 | rec_traverse(n); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_concat.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure concat(a: Node, b: Node) 4 | returns (res: Node) 5 | requires lseg(a, null) &*& lseg(b, null) 6 | ensures lseg(res, null) 7 | { 8 | if (a == null) { 9 | return b; 10 | } else { 11 | var curr := a; 12 | while (curr.next != null) 13 | invariant acc(curr) -** lseg(a, null) 14 | { 15 | curr := curr.next; 16 | } 17 | curr.next := b; 18 | return a; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_copy.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure copy(lst: Node) returns (res: Node) 4 | requires lseg(lst, null) 5 | ensures lseg(lst, null) &*& lseg(res, null) 6 | { 7 | var curr, cp: Node := lst, null; 8 | while (curr != null) 9 | invariant ((curr == null || acc(curr)) -** lseg(lst, null)) &*& lseg(cp, null) 10 | { 11 | var old_cp := cp; 12 | cp := new Node; 13 | cp.next := old_cp; 14 | curr := curr.next; 15 | } 16 | return cp; 17 | } 18 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_dispose.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure dispose(lst: Node) 4 | requires lseg(lst, null) 5 | ensures emp 6 | { 7 | while (lst != null) 8 | invariant lseg(lst, null) 9 | { 10 | var curr := lst; 11 | lst := lst.next; 12 | free(curr); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_filter.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure filter(x: Node) returns (res: Node) 4 | requires lseg(x, null) 5 | ensures lseg(res, null) 6 | { 7 | var prv: Node, curr := null, x; 8 | res := x; 9 | while (curr != null) 10 | invariant (prv.next |-> curr || prv == null &*& res == curr) -** lseg(res, null); 11 | { 12 | var old_curr := curr; 13 | curr := curr.next; 14 | var nondet: Bool; 15 | if (nondet) { 16 | if (prv != null) { 17 | prv.next := old_curr.next; 18 | } else { 19 | res := old_curr.next; 20 | } 21 | free old_curr; 22 | } else { 23 | prv := old_curr; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_insert.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure insert(lst: Node, elt: Node) 4 | returns (res: Node) 5 | requires lseg(lst, null) &*& elt.next |-> null 6 | ensures lseg(res, null) 7 | { 8 | if (lst == null) 9 | return elt; 10 | else { 11 | var nondet: Bool; 12 | var curr := lst; 13 | while (nondet && curr.next != null) 14 | invariant acc(curr) -** lseg(lst, null) 15 | { 16 | havoc nondet; 17 | curr := curr.next; 18 | } 19 | elt.next := curr.next; 20 | curr.next := elt; 21 | return lst; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_remove.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure remove(lst: Node) 4 | returns (res: Node) 5 | requires lseg(lst, null) 6 | ensures lseg(res, null) 7 | { 8 | if (lst == null) 9 | return null; 10 | else { 11 | var nondet: Bool; 12 | var curr := lst; 13 | while (nondet && curr.next != null) 14 | invariant curr != null 15 | invariant lseg(lst, curr) 16 | invariant lseg(curr, null) 17 | { 18 | havoc nondet; 19 | curr := curr.next; 20 | } 21 | 22 | var tmp := curr.next; 23 | if (tmp != null) { 24 | curr.next := tmp.next; 25 | free(tmp); 26 | } 27 | return lst; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_reverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure reverse(lst: Node) 4 | returns (rev: Node) 5 | requires lseg(lst, null) 6 | ensures lseg(rev, null) 7 | { 8 | rev := null; 9 | var curr := lst; 10 | while (curr != null) 11 | invariant lseg(rev, null) 12 | invariant lseg(curr, null) 13 | { 14 | var tmp := curr; 15 | curr := curr.next; 16 | tmp.next := rev; 17 | rev := tmp; 18 | } 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/spl/sl/sl_traverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure traverse1(lst: Node) 4 | requires lseg(lst, null) 5 | ensures lseg(lst, null) 6 | { 7 | var curr := lst; 8 | while (curr != null) 9 | invariant lseg(lst, curr) 10 | invariant lseg(curr, null) 11 | { 12 | curr := curr.next; 13 | } 14 | } 15 | 16 | procedure traverse2(lst: Node) 17 | requires lseg(lst, null) 18 | ensures lseg(lst, null) 19 | { 20 | if (lst != null) { 21 | var curr := lst; 22 | while (curr.next != null) 23 | invariant lseg(lst, curr) 24 | invariant lseg(curr, null) 25 | { 26 | curr := curr.next; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/spl/sl/union_find.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure find(x: Node, ghost root_x: Node, implicit ghost X: Set) 4 | returns (res: Node) 5 | requires lseg(x, root_x) && acc(X) &*& root_x.next |-> null 6 | ensures acc(X) &*& root_x.next |-> null &*& res == root_x 7 | ensures (forall z in X :: z.next == root_x) 8 | { 9 | var n := x.next; 10 | if (n != null) { 11 | res := find(n, root_x); 12 | x.next := res; 13 | } else { 14 | res := x; 15 | } 16 | } 17 | 18 | procedure union(x: Node, y: Node, ghost root_x: Node, ghost root_y: Node, 19 | implicit ghost X: Set, implicit ghost Y: Set) 20 | requires lseg(x, root_x) && acc(X) &+& lseg(y, root_y) && acc(Y) 21 | requires root_x.next |-> null &+& root_y.next |-> null 22 | ensures acc(X) &+& acc(Y) 23 | ensures forall z in X -- Y :: z.next == root_x // this is also OK: forall z in X :: z.next == root_x; 24 | ensures forall z in Y :: z.next == root_y 25 | ensures root_y.next |-> null &+& acc(root_x) 26 | ensures root_x == root_y || root_x.next == root_y 27 | { 28 | var t := find(x, root_x); 29 | var s := find(y, root_y); 30 | if (t != s) { 31 | t.next := s; 32 | } 33 | } 34 | 35 | procedure create() returns (res: Node) 36 | ensures lseg(res, null) && acc(res) 37 | { 38 | var n := new Node; 39 | n.next := null; 40 | return n; 41 | } 42 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_concat.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure concat(a: Node, b: Node, x: Int) returns (res: Node) 4 | requires lslseg(a, null, x) &*& uslseg(b, null, x); 5 | ensures slseg(res, null); 6 | { 7 | if (a == null) { 8 | return b; 9 | } else { 10 | var curr: Node; 11 | curr := a; 12 | while(curr.next != null) 13 | invariant curr != null &*& lslseg(a, curr, curr.data) &*& lslseg(curr, null, x); 14 | { 15 | curr := curr.next; 16 | } 17 | curr.next := b; 18 | return a; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_copy.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure copy(lst: Node) returns (res: Node) 4 | requires slseg(lst, null) 5 | ensures slseg(lst, null) &*& slseg(res, null) 6 | { 7 | if (lst == null) { 8 | return null; 9 | } else { 10 | res := new Node; 11 | var curr := lst; 12 | var cp := res; 13 | cp.data := curr.data; 14 | cp.next := null; 15 | while (curr.next != null) 16 | invariant lslseg(lst, curr, curr.data) 17 | invariant slseg(curr, null) 18 | invariant lslseg(res, cp, curr.data) 19 | invariant cp.next |-> null 20 | invariant cp.data == curr.data 21 | invariant curr != null 22 | { 23 | var old_cp: Node; 24 | old_cp := cp; 25 | cp := new Node; 26 | old_cp.next := cp; 27 | curr := curr.next; 28 | cp.data := curr.data; 29 | cp.next := null; 30 | } 31 | return res; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_dispose.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure sls_dispose(lst: Node) 4 | requires slseg(lst, null) 5 | ensures emp 6 | { 7 | var curr := lst; 8 | while (curr != null) 9 | invariant slseg(curr, null) 10 | { 11 | var tmp := curr; 12 | curr := curr.next; 13 | free tmp; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_double_all.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure sls_double_all(lst: Node) returns (res: Node) 4 | requires slseg(lst, null); 5 | ensures slseg(lst, null) &*& slseg(res, null); 6 | { 7 | if (lst == null) { 8 | return null; 9 | } else { 10 | var curr: Node, cp: Node; 11 | curr := lst; 12 | res := new Node; 13 | cp := res; 14 | cp.data := 2 * curr.data; 15 | cp.next := null; 16 | while(curr.next != null) 17 | invariant lslseg(lst, curr, curr.data); 18 | invariant slseg(curr, null); 19 | invariant lslseg(res, cp, 2 * curr.data); 20 | invariant cp.next |-> null; 21 | invariant cp.data == 2 * curr.data; 22 | invariant curr != null; 23 | { 24 | var old_cp: Node; 25 | old_cp := cp; 26 | cp := new Node; 27 | old_cp.next := cp; 28 | curr := curr.next; 29 | cp.data := 2 * curr.data; 30 | cp.next := null; 31 | } 32 | return res; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_filter.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure filter (x: Node) 4 | returns (res: Node) 5 | requires slseg(x, null) 6 | ensures slseg(res, null) 7 | { 8 | res := x; 9 | var curr := res; 10 | var prv: Node := null; 11 | while (curr != null) 12 | invariant (lslseg(res, prv, prv.data) &*& prv.next |-> curr &*& uslseg(curr, null, prv.data)) 13 | || (prv == null &*& res == curr &*& slseg(curr, null)) 14 | { 15 | var old_curr := curr; 16 | curr := curr.next; 17 | var nondet: Bool; 18 | if (nondet) { 19 | if (prv != null) { 20 | prv.next := curr; 21 | } else { 22 | res := curr; 23 | } 24 | free old_curr; 25 | } else { 26 | prv := old_curr; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_insert.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure sls_insert(lst: Node, elt: Node) returns (res: Node) 4 | requires slseg(lst, null) &*& elt.next |-> null; 5 | ensures slseg(res, null); 6 | { 7 | if (lst == null || lst.data > elt.data) { 8 | elt.next := lst; 9 | return elt; 10 | } else { 11 | var curr: Node; 12 | curr := lst; 13 | while (curr.next != null && curr.next.data <= elt.data) 14 | invariant curr != null; 15 | invariant lslseg(lst, curr, curr.data); 16 | invariant slseg(curr, null); 17 | invariant curr.data <= elt.data; 18 | { 19 | curr := curr.next; 20 | } 21 | elt.next := curr.next; 22 | curr.next := elt; 23 | return lst; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_insertion_sort.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure insertion_sort(lst: Node) 4 | requires lseg(lst, null) 5 | ensures slseg(lst, null) 6 | { 7 | var prv: Node := null; 8 | var srt := lst; 9 | while (srt != null) 10 | invariant (prv == null &*& srt == lst &*& lseg(lst, null)) 11 | || (lslseg(lst, prv, prv.data) &*& prv.next |-> srt &*& ulseg(srt, null, prv.data)) 12 | { 13 | var curr := srt.next; 14 | var min := srt; 15 | while (curr != null) 16 | invariant prv == null &*& lseg(curr, null) 17 | || ulseg(curr, null, prv.data) &*& prv.data <= min.data 18 | invariant ulseg(srt, min, min.data) 19 | invariant ulseg(min, curr, min.data) 20 | invariant min != null 21 | { 22 | if (curr.data < min.data) { 23 | min := curr; 24 | } 25 | curr := curr.next; 26 | } 27 | var tmp := min.data; 28 | min.data := srt.data; 29 | srt.data := tmp; 30 | prv := srt; 31 | srt := srt.next; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_merge_sort.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure merge(a: Node, b: Node) returns (res: Node) 4 | requires slseg(a, null) &*& slseg(b, null) 5 | ensures slseg(res, null) 6 | { 7 | res := null; 8 | if (a == null) { 9 | return b; 10 | } else if (b == null) { 11 | return a; 12 | } else if (a.data <= b.data) { 13 | res := a; 14 | a := a.next; 15 | } else { 16 | res := b; 17 | b := b.next; 18 | } 19 | 20 | var last := res; 21 | 22 | while (a != null || b != null) 23 | invariant (last.next |-> a || last.next |-> b) 24 | invariant lslseg(res, last, last.data) 25 | invariant uslseg(a, null, last.data) 26 | invariant uslseg(b, null, last.data) 27 | { 28 | if (a == null || b != null && a.data > b.data) { 29 | last.next := b; 30 | last := b; 31 | b := b.next; 32 | } else { 33 | last.next := a; 34 | last := a; 35 | a := a.next; 36 | } 37 | } 38 | return res; 39 | } 40 | 41 | procedure split_list(x: Node) returns (y: Node, z: Node) 42 | requires lseg(x, null) 43 | ensures lseg(y, null) &*& lseg(z, null) 44 | { 45 | y, z := x, x; 46 | 47 | var curr := x; 48 | while (curr != null) 49 | invariant lseg(y, z) &*& lseg(z, curr) &*& lseg(curr, null) 50 | { 51 | z := z.next; 52 | curr := curr.next; 53 | if (curr != null) { 54 | curr := curr.next; 55 | } 56 | } 57 | if (z != null) { 58 | var tmp: Node; 59 | tmp := z; 60 | z := z.next; 61 | tmp.next := null; 62 | } 63 | } 64 | 65 | 66 | procedure merge_sort(x: Node) returns (res: Node) 67 | requires lseg(x, null) 68 | ensures slseg(res, null) 69 | { 70 | var x1: Node, x2: Node; 71 | x1, x2 := split_list(x); 72 | var res1 := merge_sort(x1); 73 | var res2 := merge_sort(x2); 74 | return merge(res1, res2); 75 | } 76 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_pairwise_sum.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure sls_pairwise_sum(x: Node, y: Node) returns (z: Node) 4 | requires slseg(x, null) &*& slseg(y, null) 5 | ensures slseg(x, null) &*& slseg(y, null) &*& slseg(z, null) 6 | { 7 | if (x == null || y == null) { 8 | return null; 9 | } 10 | z := new Node; 11 | var curr_x := x; 12 | var curr_y := y; 13 | var last_z := z; 14 | z.data := curr_x.data + curr_y.data; 15 | z.next := null; 16 | while (curr_x.next != null && curr_y.next != null) 17 | invariant curr_x != null &*& lslseg(x, curr_x, curr_x.data) &*& slseg(curr_x, null) 18 | invariant curr_y != null &*& lslseg(y, curr_y, curr_y.data) &*& slseg(curr_y, null) 19 | invariant lslseg(z, last_z, last_z.data) &*& last_z.next |-> null 20 | invariant last_z.data <= curr_x.data + curr_y.data 21 | { 22 | var tmp := last_z; 23 | curr_x := curr_x.next; 24 | curr_y := curr_y.next; 25 | last_z := new Node; 26 | last_z.next := null; 27 | last_z.data := curr_x.data + curr_y.data; 28 | tmp.next := last_z; 29 | } 30 | return z; 31 | } 32 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_quicksort.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure split_list(x: Node, y: Node, lb: Int, ub: Int) returns (pivot: Node) 4 | requires blseg(x, y, lb, ub) &*& x != y 5 | ensures blseg(x, pivot, lb, pivot.data) 6 | ensures blseg(pivot, y, pivot.data, ub) &*& pivot != y 7 | ensures lb <= pivot.data <= ub 8 | ensures Btwn(next, x, pivot, y) 9 | { 10 | var curr := x.next; 11 | pivot := x; 12 | 13 | while (curr != y) 14 | invariant blseg(x, pivot, lb, pivot.data) 15 | invariant blseg(pivot, curr, pivot.data, ub) &*& pivot != curr 16 | invariant blseg(curr, y, lb, ub) 17 | invariant lb <= pivot.data <= ub 18 | invariant Btwn(next, x, pivot, y) 19 | invariant Btwn(next, pivot, curr, y) 20 | { 21 | if (curr.data < pivot.data) { 22 | var tmp := curr.data; 23 | curr.data := pivot.next.data; 24 | pivot.next.data := pivot.data; 25 | pivot.data := tmp; 26 | pivot := pivot.next; 27 | } 28 | curr := curr.next; 29 | } 30 | } 31 | 32 | procedure quicksort(x: Node, y: Node, ghost lb: Int, ghost ub: Int) 33 | requires blseg(x, y, lb, ub) 34 | ensures bslseg(x, y, lb, ub) 35 | { 36 | if (x != y && x.next != y) { 37 | var pivot := split_list(x, y, lb, ub); 38 | quicksort(x, pivot, lb, pivot.data); 39 | quicksort(pivot.next, y, pivot.data, ub); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_quicksort_wo_split_impl.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure split(x: Node, y: Node, lb: Int, ub: Int) returns (pivot: Node) 4 | requires blseg(x, y, lb, ub) &*& x != y 5 | ensures blseg(x, pivot, lb, pivot.data) 6 | ensures blseg(pivot, y, pivot.data, ub) &*& pivot != y 7 | ensures pivot.data >= lb &*& pivot.data <= ub 8 | //ensures Btwn(next, x, pivot, y); 9 | 10 | 11 | procedure quicksort(x: Node, y: Node, ghost lb: Int, ghost ub: Int) 12 | requires blseg(x, y, lb, ub) 13 | ensures bslseg(x, y, lb, ub) 14 | { 15 | if (x != y && x.next != y) { 16 | var pivot := split(x, y, lb, ub); 17 | quicksort(x, pivot, lb, pivot.data); 18 | quicksort(pivot.next, y, pivot.data, ub); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_remove.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure remove(lst: Node, value: Int) returns (res: Node) 4 | requires slseg(lst, null); 5 | ensures slseg(res, null); 6 | { 7 | var curr: Node, prv: Node; 8 | prv := null; 9 | curr := lst; 10 | while (curr != null && curr.data < value) 11 | invariant prv == null &*& curr == lst &*& slseg(curr, null) || 12 | lslseg(lst, prv, prv.data) &*& prv.next |-> curr &*& slseg(curr, null) &*& 13 | (curr == null || prv.data <= curr.data); 14 | { 15 | prv := curr; 16 | curr := curr.next; 17 | } 18 | if (curr != null && curr.data == value) { 19 | if (prv == null) { 20 | lst := curr.next; 21 | } else { 22 | prv.next := curr.next; 23 | } 24 | free curr; 25 | } 26 | return lst; 27 | } 28 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_reverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure reverse(lst: Node) returns (rev: Node) 4 | requires slseg(lst, null); 5 | ensures rslseg(rev, null); 6 | { 7 | var curr: Node; 8 | curr := lst; 9 | rev := null; 10 | while (curr != null) 11 | invariant (rev == null &*& slseg(curr, null)) || (rslseg(rev, null) &*& uslseg(curr, null, rev.data)); 12 | { 13 | var tmp: Node; 14 | tmp := curr; 15 | curr := curr.next; 16 | tmp.next := rev; 17 | rev := tmp; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/spl/sls/sls_traverse.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | procedure sls_traverse(lst: Node) 4 | requires slseg(lst, null) 5 | ensures slseg(lst, null) 6 | { 7 | var curr: Node; 8 | curr := lst; 9 | while (curr != null) 10 | //invariant (curr != null &*& lslseg(lst, curr, curr.data) &*& slseg(curr, null)) || (curr == null &*& slseg(lst, curr)) 11 | invariant (curr == null || acc(curr)) -** slseg(lst, null) 12 | { 13 | curr := curr.next; 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness0.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure soundness0(x: Node) 4 | requires lseg(x, null); 5 | ensures lseg(x, null); 6 | { 7 | assert false; 8 | } 9 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness1.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure soundness1(x: Node) 4 | requires lseg(x, null); 5 | ensures lseg(x, null); 6 | { 7 | var curr: Node; 8 | curr := x; 9 | while (curr != null) 10 | invariant lseg(x, curr) &*& lseg(curr, null); 11 | { 12 | assert !true; 13 | curr := curr.next; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness2.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | // Faulty filtering of a singly-linked list: 4 | // the access to curr.next at the end of the loop happens after freeing curr. 5 | 6 | procedure soundness2(x: Node) 7 | returns (y: Node) 8 | requires lseg(x, null) 9 | ensures lseg(y, null) 10 | { 11 | var curr: Node, prv: Node; 12 | y := x; 13 | prv := null; 14 | curr := y; 15 | while (curr != null) 16 | invariant ((lseg(y, prv) &*& prv.next |-> curr || prv == null &*& y == curr) &*& lseg(curr, null)) 17 | { 18 | var nondet: Bool; 19 | if (nondet) { 20 | if (prv != null) { 21 | prv.next := curr.next; 22 | } else { 23 | y := curr.next; 24 | } 25 | free curr; 26 | } else { 27 | prv := curr; 28 | } 29 | // possible access to freed location 30 | curr := curr.next; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness3.spl: -------------------------------------------------------------------------------- 1 | include "../include/dllist.spl"; 2 | 3 | // Insertion into a doubly-linked list. 4 | // The bug is that the procedure might not return the head of the list when elt is inserted before a. 5 | 6 | /* 7 | procedure soundness3(a: Node, b: Node, elt: Node) returns (c: Node, d: Node) 8 | requires dlseg(a, null, null, b) &*& elt.next |-> null; 9 | ensures dlseg(c, null, null, d); 10 | { 11 | if (a == null) { 12 | elt.prev := null; 13 | return elt, elt; 14 | } else { 15 | var curr: Node, prv: Node; 16 | c, d := a, b; 17 | curr := c; 18 | prv := null; 19 | var nondet: Bool; 20 | while (nondet && curr.next != null) 21 | invariant curr != null &*& dlseg(c, null, curr, prv) &*& dlseg(curr, prv, null, d); 22 | { 23 | prv := curr; 24 | curr := curr.next; 25 | havoc nondet; 26 | } 27 | elt.next := curr; 28 | curr.prev := elt; 29 | if (prv != null) { 30 | prv.next := elt; 31 | } else { 32 | // c := elt; 33 | } 34 | elt.prev := prv; 35 | return c, d; 36 | } 37 | } 38 | */ 39 | 40 | procedure soundness3(a: Node, b: Node, elt: Node, c: Node, d: Node, curr: Node, prv: Node) 41 | returns (c1: Node) 42 | requires curr != null &*& dlseg(c, null, curr, prv) &*& dlseg(curr, prv, null, d) &*& elt.next |-> null; 43 | ensures dlseg(c1, null, null, d); 44 | { 45 | elt.next := curr; 46 | curr.prev := elt; 47 | if (prv != null) { 48 | prv.next := elt; 49 | } else { 50 | //c1 := elt; 51 | } 52 | elt.prev := prv; 53 | return c1; 54 | } 55 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness4.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | // loop was underconstrained 4 | // forgot the constraints that link the last elements 5 | 6 | procedure sls_pairwise_sum(x: Node, y: Node) 7 | returns (z: Node) 8 | requires slseg(x, null) &*& slseg(y, null) 9 | ensures slseg(x, null) &*& slseg(y, null) &*& slseg(z, null) 10 | { 11 | if (x == null || y == null) { 12 | return null; 13 | } 14 | var curr_x: Node, curr_y: Node, last_z: Node; 15 | curr_x := x; 16 | curr_y := y; 17 | z := new Node; 18 | last_z := z; 19 | z.data := curr_x.data + curr_y.data; 20 | z.next := null; 21 | while (curr_x.next != null && curr_y.next != null) 22 | invariant curr_x != null &*& lslseg(x, curr_x, curr_x.data) &*& slseg(curr_x, null) 23 | invariant curr_y != null &*& lslseg(y, curr_y, curr_y.data) &*& slseg(curr_y, null) 24 | invariant lslseg(z, last_z, last_z.data) &*& last_z.next |-> null 25 | //invariant last_z.data <= curr_x.data + curr_y.data; 26 | { 27 | var tmp: Node; 28 | tmp := last_z; 29 | curr_x := curr_x.next; 30 | curr_y := curr_y.next; 31 | last_z := new Node; 32 | last_z.next := null; 33 | last_z.data := curr_x.data + curr_y.data; 34 | tmp.next := last_z; 35 | } 36 | return z; 37 | } 38 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness5.spl: -------------------------------------------------------------------------------- 1 | include "../include/slslist.spl"; 2 | 3 | // quicksort: the postcondition of split is too weak and gives a panhandle list. 4 | 5 | procedure predecessor(start: Node, end: Node, ghost lb: Int, ghost ub: Int) 6 | returns (prv: Node) 7 | requires blseg(start, end, lb, ub) 8 | requires start != end 9 | ensures blseg(start, prv, lb, ub) 10 | ensures acc(prv) &*& prv.next == end 11 | ensures prv != end 12 | ensures prv.data >= lb &*& prv.data <= ub 13 | { 14 | var prv: Node; 15 | prv := start; 16 | while (prv.next != end) 17 | invariant blseg(start, prv, lb, ub) 18 | invariant blseg(prv, end, lb, ub) 19 | invariant prv != end 20 | invariant prv.data >= lb &*& prv.data <= ub 21 | { 22 | prv := prv.next; 23 | } 24 | return prv; 25 | } 26 | 27 | procedure split(lst: Node, tsl: Node, lb: Int, ub: Int) 28 | returns (res: Node) 29 | requires blseg(lst, tsl, lb, ub) &*& lst != tsl 30 | ensures blseg(lst, res, lb, res.data) 31 | ensures blseg(res, tsl, res.data, ub) &*& res != tsl 32 | ensures res.data >= lb &*& res.data <= ub 33 | { 34 | var pivot: Node, start: Node, end: Node; 35 | pivot := predecessor(lst, tsl, lb, ub); 36 | end := pivot; 37 | start := lst; 38 | while (start != end) 39 | invariant blseg(lst, start, lb, pivot.data) 40 | invariant blseg(start, end, lb, ub) 41 | invariant blseg(end, pivot, pivot.data, ub) 42 | invariant pivot.next |-> tsl 43 | invariant pivot.data >= lb 44 | invariant pivot.data <= ub 45 | { 46 | if (start.data <= pivot.data) { 47 | start := start.next; 48 | } else if (end.data > pivot.data) { 49 | end := predecessor(start, end, lb, ub); 50 | } else { 51 | var tmp: Int; 52 | tmp := start.data; 53 | start.data := end.data; 54 | end.data := tmp; 55 | } 56 | } 57 | var tmp2: Int; 58 | tmp2 := pivot.data; 59 | pivot.data := end.data; 60 | end.data := tmp2; 61 | return end; 62 | } 63 | 64 | 65 | procedure quicksort(lst: Node, tsl: Node, ghost lb: Int, ghost ub: Int) 66 | requires blseg(lst, tsl, lb, ub) 67 | ensures bslseg(lst, tsl, lb, ub) 68 | { 69 | if (lst != tsl && lst.next != tsl) { 70 | var pivot: Node; 71 | pivot := split(lst, tsl, lb, ub); 72 | quicksort(lst, pivot, lb, pivot.data); 73 | quicksort(pivot.next, tsl, pivot.data, ub); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness6.spl: -------------------------------------------------------------------------------- 1 | include "../include/slsset.spl"; 2 | 3 | procedure traverse(lst: Node, val: Int, 4 | implicit ghost content: Set) 5 | requires list_set(lst, null, content) 6 | ensures list_set(lst, null, content) 7 | { 8 | var curr: Node; 9 | curr := lst; 10 | var c1: Set, c2: Set; 11 | c1 := content; 12 | c2 := Set(); 13 | 14 | while (curr != null) 15 | //the case split is needed because of curr.data 16 | invariant (curr != null &*& list_set(lst, curr, c2) &*& list_set(curr, null, c1)) 17 | || (curr == null &*& list_set(lst, curr, c2) &*& c1 == Set()) 18 | invariant content == c1 ++ c2 19 | //invariant curr == null || (curr.data >= lb && curr.data < ub) 20 | { 21 | c1 := c1 ++ Set(curr.data); //BUG here: should be -- 22 | c2 := c2 ++ Set(curr.data); 23 | curr := curr.next; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness7.spl: -------------------------------------------------------------------------------- 1 | include "../include/bstree.spl"; 2 | 3 | procedure contains(root: Node, val: Int) 4 | returns (res: Bool) 5 | requires tree(root) 6 | ensures tree(root) 7 | { 8 | var cur: Node; 9 | cur := root; 10 | while (cur != null && cur.data != val) 11 | invariant tree(cur) //non empty frame after loop iteration 12 | { 13 | if (cur.data > val) { 14 | cur := cur.left; 15 | } else { 16 | cur := cur.right; 17 | } 18 | } 19 | if (cur == null) { 20 | return false; 21 | } else { 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness8.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure soudness8(lst: Node) 4 | returns (res: Node) 5 | requires lseg(lst, null) 6 | ensures lseg(res, null) 7 | { 8 | if (lst == null) 9 | return null; 10 | else { 11 | var nondet: Bool, curr: Node; 12 | curr := lst; 13 | while (nondet && curr.next != null) 14 | invariant curr != null 15 | invariant lseg(lst, curr) 16 | invariant lseg(curr, null) 17 | { 18 | havoc nondet; 19 | curr := curr.next; 20 | } 21 | var tmp: Node; 22 | tmp := curr.next; 23 | if (tmp == null) { 24 | } else { 25 | curr.next := tmp.next; 26 | // forgot to free tmp 27 | // free(tmp); 28 | } 29 | return lst; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/spl/soundness/soundness9.spl: -------------------------------------------------------------------------------- 1 | include "../include/sllist.spl"; 2 | 3 | procedure filter(x: Node) returns (res: Node) 4 | requires lseg(x, null) 5 | ensures lseg(res, null) 6 | { 7 | var prv: Node, curr := null, x; 8 | res := x; 9 | while (curr != null) 10 | invariant (prv.next |-> curr || prv == null &*& res == curr) -** lseg(res, null); 11 | { 12 | var old_curr := curr; 13 | curr := curr.next; 14 | var nondet: Bool; 15 | if (nondet) { 16 | if (prv != null) { 17 | prv.next := old_curr.next; 18 | } else { 19 | res := old_curr.next; 20 | } 21 | // free old_curr; memory leak here 22 | } else { 23 | prv := old_curr; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/symb_exec/dirty.spl: -------------------------------------------------------------------------------- 1 | options "-symbexec" 2 | 3 | struct Node { 4 | var next: Node; 5 | } 6 | 7 | 8 | procedure lemma_clean(x: Node) 9 | requires [x.next |-> null](x) 10 | ensures x.next |-> null 11 | 12 | procedure test1(x: Node, y: Node) 13 | requires [x.next |-> null](x) &*& acc(y) 14 | ensures acc(x) &*& acc(y) 15 | { 16 | lemma_clean(x); 17 | } 18 | 19 | procedure write_dirty(x: Node, y: Node, z: Node) 20 | requires [x.next |-> null &*& acc(z)](x) &*& y.next |-> x 21 | ensures [x.next |-> x &*& acc(z)](x) &*& y.next |-> x 22 | { 23 | x.next := x; 24 | } 25 | 26 | procedure write_dirty2(x: Node, y: Node, z: Node) 27 | requires [[x.next |-> null](x) &*& acc(z)](x) &*& y.next |-> x 28 | ensures [[x.next |-> x](x) &*& acc(z)](x) &*& y.next |-> x 29 | { 30 | x.next := x; 31 | } 32 | -------------------------------------------------------------------------------- /tests/spl/symb_exec/list.spl: -------------------------------------------------------------------------------- 1 | options "-symbexec" 2 | 3 | struct Node { 4 | var next: Node; 5 | } 6 | 7 | predicate lseg(x: Node, y: Node) { 8 | true // Assuming: x == y && emp || exists z: Node :: x != y &*& x.next |-> z &*& lseg(z, y) 9 | } 10 | 11 | 12 | procedure lemma_unfold_lseg(x: Node, y: Node) returns (z: Node) 13 | requires lseg(x, y) &*& x != y 14 | ensures x.next |-> z &*& lseg(z, y) 15 | 16 | procedure lemma_fold_lseg(x: Node, z: Node, y: Node) 17 | requires x.next |-> z &*& lseg(z, y) &*& x != y 18 | ensures lseg(x, y) 19 | 20 | 21 | procedure test_unfold(x: Node) returns (y: Node) 22 | requires lseg(x, null) &*& x != null 23 | ensures x.next |-> y &*& lseg(y, null) 24 | { 25 | var z := lemma_unfold_lseg(x, null); 26 | y := x.next; 27 | } 28 | 29 | procedure append_front(x: Node, y: Node) 30 | requires acc(x) &*& lseg(y, null) 31 | ensures lseg(x, null) 32 | { 33 | x.next := y; 34 | lemma_fold_lseg(x, y, null); 35 | } 36 | -------------------------------------------------------------------------------- /tests/spl/symb_exec/soundness_arr1.spl: -------------------------------------------------------------------------------- 1 | options "-symbexec" 2 | 3 | procedure read_fail(a: Array) returns (x: Int) 4 | requires acc(a) &*& a.length == 2 &*& (forall j: Int :: 0 <= j && j < a.length ==> a[j] == 0) 5 | ensures acc(a) 6 | { 7 | x := a[3]; 8 | a[0] := 0; 9 | } 10 | -------------------------------------------------------------------------------- /tests/spl/symb_exec_v2/basic.spl: -------------------------------------------------------------------------------- 1 | options "-symbexec-v2" 2 | 3 | procedure assign(x: Int, y: Int) 4 | requires x == 0 && y == x 5 | ensures x == 10 && y == 0 6 | { 7 | x := 5; 8 | x := 10; 9 | } 10 | 11 | procedure assign2(x: Int, y: Int) 12 | requires x == 0 && y == 1 13 | ensures x == 10 && y == 5 14 | { 15 | x := 5; 16 | y := 3; 17 | x := x; 18 | x := 10; 19 | y := 5; 20 | y := y; 21 | } 22 | -------------------------------------------------------------------------------- /tests/spl/tree/skew_heap/extractMax.spl: -------------------------------------------------------------------------------- 1 | include "../../include/bstree.spl"; 2 | 3 | procedure union(h1: Node, h2: Node, 4 | implicit ghost content1: Set, 5 | implicit ghost content2: Set) 6 | returns (res: Node) 7 | requires heap_set(h1, content1) &*& heap_set(h2, content2); 8 | ensures heap_set(res, content1 ++ content2); 9 | 10 | 11 | procedure extractMax(h: Node, 12 | implicit ghost content: Set) 13 | returns (max: Int, rest: Node) 14 | requires heap_set(h, content) &*& h != null &*& h.parent == null 15 | ensures exists remaining: Set :: heap_set(rest, remaining) &*& content == Set(max) ++ remaining 16 | ensures forall x in content :: max >= x 17 | { 18 | var d : Int; 19 | d := h.data; 20 | var hp: Node, r: Node, l: Node; 21 | l := h.left; 22 | r := h.right; 23 | h.left := null; 24 | h.right := null; 25 | if (l != null) { l.parent := null; } 26 | if (r != null) { r.parent := null; } 27 | hp := union(l, r); 28 | free h; 29 | return d, hp; 30 | } 31 | -------------------------------------------------------------------------------- /tests/spl/tree/skew_heap/insert.spl: -------------------------------------------------------------------------------- 1 | include "../../include/bstree.spl"; 2 | 3 | procedure union(h1: Node, h2: Node, 4 | implicit ghost content1: Set, 5 | implicit ghost content2: Set) 6 | returns (res: Node) 7 | requires heap_set(h1, content1) &*& heap_set(h2, content2); 8 | ensures heap_set(res, content1 ++ content2); 9 | 10 | 11 | procedure insert(h: Node, value: Int, 12 | implicit ghost content: Set) 13 | returns (res: Node) 14 | requires heap_set(h, content); 15 | ensures heap_set(res, content ++ Set(value)); 16 | { 17 | var n: Node; 18 | n := new Node; 19 | n.left := null; 20 | n.right := null; 21 | n.parent := null; 22 | n.data := value; 23 | return union(h, n); 24 | } 25 | -------------------------------------------------------------------------------- /tests/spl/tree/skew_heap/union.spl: -------------------------------------------------------------------------------- 1 | include "../../include/bstree.spl"; 2 | 3 | procedure union(h1: Node, h2: Node, 4 | implicit ghost content1: Set, 5 | implicit ghost content2: Set) 6 | returns (res: Node) 7 | requires heap_set(h1, content1) &*& heap_set(h2, content2); 8 | ensures heap_set(res, content1 ++ content2); 9 | { 10 | if (h1 == null) { 11 | return h2; 12 | } else if (h2 == null) { 13 | return h1; 14 | } else if (h1.data >= h2.data) { 15 | var u: Node, r: Node; 16 | r := h1.right; 17 | h1.right := h1.left; 18 | if (r != null) { r.parent := null; } 19 | u := union(h2, r); 20 | h1.left := u; 21 | if (u != null) { u.parent := h1; } 22 | return h1; 23 | } else { 24 | return union(h2, h1); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/spl/tree/skew_heap_no_content.spl: -------------------------------------------------------------------------------- 1 | include "../include/bstree.spl"; 2 | 3 | procedure union(h1: Node, h2: Node) 4 | returns (res: Node) 5 | requires heap(h1) &*& heap(h2) 6 | ensures heap(res) 7 | { 8 | if (h1 == null) { 9 | return h2; 10 | } else if (h2 == null) { 11 | return h1; 12 | } else if (h1.data >= h2.data) { 13 | var u: Node, r: Node; 14 | r := h1.right; 15 | h1.right := h1.left; 16 | if (r != null) { r.parent := null; } 17 | u := union(h2, r); 18 | h1.left := u; 19 | if (u != null) { u.parent := h1; } 20 | return h1; 21 | } else { 22 | return union(h2, h1); 23 | } 24 | } 25 | 26 | procedure extractMax(h: Node) 27 | returns (max: Int, rest: Node) 28 | requires heap(h) &*& h != null 29 | ensures heap(rest) 30 | { 31 | var d : Int; 32 | d := h.data; 33 | var hp: Node, r: Node, l: Node; 34 | l := h.left; 35 | r := h.right; 36 | h.parent := null; 37 | free h; 38 | if (l != null) { l.parent := null; } 39 | if (r != null) { r.parent := null; } 40 | hp := union(l, r); 41 | if (hp != null) { hp.parent := null; } 42 | return d, hp; 43 | } 44 | 45 | procedure insert(h: Node, value: Int) 46 | returns (res: Node) 47 | requires heap(h) 48 | ensures heap(res) 49 | { 50 | var n: Node; 51 | n := new Node; 52 | n.left := null; 53 | n.right := null; 54 | n.parent := null; 55 | n.data := value; 56 | return union(h, n); 57 | } 58 | -------------------------------------------------------------------------------- /tests/spl/tree/union_find.spl: -------------------------------------------------------------------------------- 1 | struct Node { 2 | var next: Node; 3 | ghost var gnext: Node; 4 | } 5 | 6 | function rep(x: Node) returns (res: Node) 7 | requires acc({y: Node :: Reach(next, x, y) && y != null}) 8 | ensures 9 | Reach(next, x, null) && x != null ==> 10 | Reach(next, x, res) && res != null && 11 | res.next == null 12 | ensures 13 | !Reach(next, x, null) || x == null ==> res == null 14 | @(matching x yields rep(rep(x))) 15 | 16 | predicate next_eq_gnext(X: Set) 17 | requires acc(X) 18 | { 19 | forall x: Node, y: Node, z: Node :: 20 | x in X && z in X ==> 21 | Btwn(next, x, y, z) == Btwn(gnext, x, y, z) 22 | } 23 | 24 | predicate eqclass(x: Node, X: Set) { 25 | acc(X) &*& 26 | X == { z: Node :: Reach(gnext, z, rep(x)) } && 27 | rep(x).gnext == null && 28 | x in X && 29 | next_eq_gnext(X) 30 | } 31 | 32 | procedure lemma_rep_is_idempotent(x: Node) 33 | requires acc({y: Node :: Reach(next, x, y) && y != null}) 34 | ensures acc({y: Node :: Reach(next, x, y) && y != null}) 35 | ensures rep(x) == rep(rep(x)) 36 | { 37 | } 38 | 39 | procedure lemma_rep_non_null(x: Node, X: Set) 40 | requires eqclass(x, X) 41 | ensures eqclass(x, X) 42 | ensures rep(x) != null 43 | { 44 | } 45 | 46 | procedure lemma_rep_has_same_eqclass(x: Node, X: Set, Y: Set) 47 | requires eqclass(x, X) 48 | ensures eqclass(rep(x), X) 49 | { 50 | } 51 | 52 | 53 | procedure find(x: Node, implicit ghost X: Set) 54 | returns (res: Node) 55 | requires eqclass(x, X) 56 | ensures eqclass(x, X) 57 | ensures res == rep(x) && rep(x) == old(rep(x)) 58 | { 59 | var n: Node; 60 | n := x.next; 61 | if (n != null) { 62 | res := find(n); 63 | x.next := res; 64 | x.gnext := res; 65 | return res; 66 | } else { 67 | return x; 68 | } 69 | } 70 | 71 | procedure union(x: Node, y: Node, 72 | implicit ghost X: Set, 73 | implicit ghost Y: Set) 74 | requires eqclass(x, X) &+& eqclass(y, Y) 75 | ensures eqclass(y, X ++ Y) 76 | { 77 | var t: Node, s: Node; 78 | t := find(x); 79 | s := find(y); 80 | if (t != s) { 81 | t.next := s; 82 | t.gnext := s; 83 | } 84 | } 85 | 86 | procedure create() returns (res: Node) 87 | ensures eqclass(res, {res}) 88 | { 89 | res := new Node; 90 | res.next := null; 91 | } 92 | -------------------------------------------------------------------------------- /tests/spl/work_in_progress/bag_test.spl: -------------------------------------------------------------------------------- 1 | include "../include/bag.spl"; 2 | 3 | procedure test00() 4 | { 5 | assert( min(0, 2) == 0 ); 6 | } 7 | 8 | procedure test01() 9 | { 10 | assert( max(0, 2) == 2 ); 11 | } 12 | 13 | procedure test02(x: Bag, y: Bag) 14 | { 15 | assert( sum(x, y) == sum(union(x,y), intersection(x,y)) ); 16 | } 17 | -------------------------------------------------------------------------------- /tests/spl/work_in_progress/link_and_array/btree_simple_array/find.spl: -------------------------------------------------------------------------------- 1 | include "def_local.spl"; 2 | 3 | /* Find the smallest value >= x in this BTree */ 4 | procedure find(bt: Node, x: T) returns (res: T) 5 | requires btree_root(bt) 6 | requires x != bottom && x != top 7 | ensures btree_root(bt) 8 | { 9 | var z: T := bottom; 10 | var n := bt; 11 | var flag := false; 12 | while (n != null && !flag) 13 | invariant x != bottom && x != top 14 | //invariant lt(n.lbound, x) && lt(x, n.ubound) 15 | invariant (n == null || acc(n)) -** btree_root(bt) 16 | { 17 | var i := findIt(n.keys, x); 18 | if (i < n.keys.length && n.keys[i] == x) { 19 | z := n.keys[i]; 20 | flag := true; /* Found x, so return */ 21 | } else { 22 | /* n.keys[i] is smallest value > x, go to child[i] if exists */ 23 | if (i < n.keys.length && n.keys[i] != top) { 24 | z := n.keys[i]; 25 | } 26 | n := n.children[i]; 27 | } 28 | } 29 | return z; 30 | } 31 | 32 | procedure findIt(a: Array, x: T) returns (idx: Int) 33 | requires sorted_key_array(a) 34 | requires x != top 35 | ensures sorted_key_array(a) 36 | // what we actually care about 37 | ensures idx == index_of_key(a, x) 38 | { 39 | var lo := 0; 40 | var hi := a.length; 41 | 42 | while (hi != lo) 43 | invariant x != top 44 | invariant sorted_key_array(a) 45 | // what we actually care about 46 | invariant 0 <= lo && lo <= hi && hi <= a.length 47 | invariant hi == a.length || a[lo] == x || lt(x, a[hi]) 48 | invariant forall i: Int :: 0 <= i < lo ==> lt(a[i], x) 49 | invariant forall i: Int :: hi < i < a.length ==> lt(x, a[i]) 50 | { 51 | var m := (hi + lo) / 2; 52 | var cmp: Int; 53 | cmp := compare(x, a[m]); 54 | if (cmp < 0) { 55 | hi := m; // look in first half 56 | } else if (cmp > 0) { 57 | lo := m+1; // look in second half 58 | } else { 59 | // found it 60 | hi := m; 61 | lo := m; 62 | } 63 | } 64 | return lo; 65 | } 66 | -------------------------------------------------------------------------------- /tests/spl/work_in_progress/sls/sls_merge_sort_abstract.spl: -------------------------------------------------------------------------------- 1 | struct Node { 2 | var next: Node; 3 | var data: Int; 4 | } 5 | 6 | function lseg_footprint(next: Map, x: Node, y: Node) 7 | returns (FP: Set) 8 | 9 | predicate lseg(x: Node, y: Node) { 10 | acc(lseg_footprint(next, x, y)) 11 | } 12 | 13 | predicate slseg(data: Map, x: Node, y: Node) { 14 | acc(lseg_footprint(next, x, y)) 15 | } 16 | 17 | procedure merge(a: Node, b: Node) returns (res: Node) 18 | requires slseg(data, a, null) &*& slseg(data, b, null) 19 | ensures slseg(data, res, null) 20 | 21 | procedure split(x: Node) returns (y: Node, z: Node) 22 | requires lseg(x, null) 23 | ensures lseg(y, null) &*& lseg(z, null) 24 | 25 | procedure merge_sort(x: Node) returns (res: Node) 26 | requires lseg(x, null) 27 | ensures slseg(data, res, null) 28 | { 29 | var x1: Node, x2: Node; 30 | x1, x2 := split(x); 31 | var res1 := merge_sort(x1); 32 | var res2 := merge_sort(x2); 33 | return merge(res1, res2); 34 | } 35 | -------------------------------------------------------------------------------- /tests/spl/work_in_progress/tree/todo: -------------------------------------------------------------------------------- 1 | 2 | Priority: 3 | set as AAT functional correctness 4 | AVL tree without balanced property 5 | RB tree without balanced property 6 | quad tree 7 | 8 | search tree / sets 9 | red-black tree 10 | AVL tree 11 | AA tree 12 | proving functional correctness of search tree requires reasoning about map (array property fragment ?) 13 | 14 | heap: 15 | binary heap 16 | fibonacci heap 17 | leftist heap 18 | 19 | space partition tree: 20 | quad tree 21 | oct tree 22 | k-d tree 23 | 24 | -------------------------------------------------------------------------------- /tests/test.spl: -------------------------------------------------------------------------------- 1 | procedure node_arraymove(length: Int) 2 | { 3 | if (length > 0) { 4 | var i := length - 1; 5 | while (i >= 0) 6 | invariant -1 <= i && i < length 7 | { 8 | i := i - 1; 9 | } 10 | //return ; // XXX 11 | } else if (length < 0){ 12 | var i := 0; 13 | while (i < length) 14 | invariant 0 <= i && i <= length 15 | { 16 | i := i + 1; 17 | } 18 | //return ; // XXX 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /vim/ftdetect/spl.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.spl set filetype=spl 2 | 3 | -------------------------------------------------------------------------------- /vim/syntax/spl.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: SPL 3 | " Maintainer: Damien Zufferey 4 | " First Release: ??? 5 | " Last Change: ??? 6 | " Version: 0.1 7 | 8 | if exists("b:current_syntax") 9 | finish 10 | endif 11 | 12 | " case is significant 13 | " syn case ignore 14 | " spl Keywords 15 | syn keyword splStatement include procedure returns if else while return new var free 16 | syn keyword splStatement axiom assert assume requires ensures invariant matching yields 17 | syn keyword splStatement struct function predicate pure ghost implicit type 18 | syn keyword splTodo contained TODO ToDo Todo todo XXX FIXME 19 | " spl Types 20 | syn keyword splType Bool Int Node 21 | syn region splType start="Array<" end=">" contains=splType 22 | syn region splType start="Loc<" end=">" contains=splType 23 | syn region splType start="Set<" end=">" contains=splType 24 | syn region splType start="Map<" end=">" contains=splType 25 | " Operators and special characters 26 | syn keyword splOperator exists forall 27 | syn match splOperator "!" 28 | syn match splOperator "=" 29 | syn match splOperator "&&" 30 | syn match splOperator "&*&" 31 | syn match splOperator "||" 32 | syn match splOperator "!" 33 | syn match splOperator "+" 34 | syn match splOperator "*" 35 | syn match splOperator "/" 36 | syn match splOperator "-" 37 | syn match splOperator "<" 38 | syn match splOperator ">" 39 | syn match splSpecial "\." 40 | syn match splSpecial "\[" 41 | syn match splSpecial "\]" 42 | syn match splSpecial ":=" 43 | " literal 44 | syn region splLiteral start=+"+ end=+"+ oneline 45 | syn match splLiteral "'[^\\]'" 46 | syn keyword splLiteral true false 47 | syn keyword splLiteral null 48 | syn match splLiteral "-\=\<\d\+\>" 49 | syn match splLiteral "0x\x\+" 50 | " spl Comments 51 | syn region splComment start="/\*" end="\*/" contains=splTodo,@Spell 52 | syn match splComment "//.*" contains=splTodo,@Spell 53 | 54 | " Class Linking 55 | hi def link splStatement Statement 56 | hi def link splType Type 57 | hi def link splComment Comment 58 | hi def link splOperator Special 59 | hi def link splSpecial Special 60 | hi def link splLiteral String 61 | hi def link splTodo Todo 62 | 63 | let b:current_syntax = "spl" 64 | --------------------------------------------------------------------------------