diff --git a/lexer.l b/lexer.l index 9ba782a..b35ebfc 100644 --- a/lexer.l +++ b/lexer.l @@ -93,6 +93,7 @@ KEYWORD :[a-zA-Z0-9._+\-*=%/?!$_~&^<>@]+ "exit" { return TK_EXIT; } "pop" { return TK_POP; } "push" { return TK_PUSH; } +"reset" { return TK_RESET; } "set-info" { return TK_SET_INFO; } "set-logic" { return TK_SET_LOGIC; } "set-option" { return TK_SET_OPTION; } @@ -101,6 +102,13 @@ KEYWORD :[a-zA-Z0-9._+\-*=%/?!$_~&^<>@]+ ":pattern" { return TK_PATTERN; } ":named" { return TK_NAMED; } +":qid" { return TK_QID; } +":no-pattern" { return TK_NOPATTERN; } +":skolemid" { return TK_SKOLEMID; } +":lblpos" { return TK_LBLPOS; } +":lblneg" { return TK_LBLNEG; } +":weight" { return TK_WEIGHT; } + {NUMERAL} { yylval.string = c_strdup(yytext); return NUMERAL; } {DECIMAL} { yylval.string = c_strdup(yytext); return DECIMAL; } {HEXADECIMAL} { yylval.string = c_strdup(yytext); return HEXADECIMAL; } diff --git a/parser.y b/parser.y index 55de0b4..573ae35 100644 --- a/parser.y +++ b/parser.y @@ -44,6 +44,10 @@ void yyerror(const char *s); using namespace scrambler; +extern bool support_non_smtcomp; + +extern bool support_z3; + %} %locations @@ -101,6 +105,18 @@ using namespace scrambler; %token TK_PATTERN ":pattern" %token TK_NAMED ":named" +// begin non-smtcomp tokens + +%token TK_RESET "reset" +%token TK_QID ":qid" +%token TK_NOPATTERN ":no-pattern" +%token TK_SKOLEMID ":skolemid" +%token TK_LBLPOS ":lblpos" +%token TK_LBLNEG ":lblneg" +%token TK_WEIGHT ":weight" + +// end non-smtcomp tokens + %type sort_dec_list %type sort_dec %type datatype_dec_list @@ -200,6 +216,7 @@ command : | cmd_exit | cmd_pop | cmd_push +| cmd_reset | cmd_set_logic | cmd_set_info | cmd_set_option @@ -344,6 +361,17 @@ cmd_push : '(' TK_PUSH NUMERAL ')' } ; +cmd_reset : '(' TK_RESET ')' + { + if (!support_non_smtcomp) { + // not allowed in SMT-COMP + yyerror("Encountered non-SMT-COMP command: 'reset'. Maybe you " + "want to re-run with '-support-non-smtcomp true'."); + } + add_node("reset"); + } +; + cmd_set_info : '(' TK_SET_INFO KEYWORD ')' { @@ -371,11 +399,16 @@ cmd_set_logic : '(' TK_SET_LOGIC SYMBOL ')' // core track only cmd_set_option : '(' TK_SET_OPTION KEYWORD attribute_value ')' { - if (strcmp($3, ":produce-unsat-cores") != 0 || $4->symbol != "true") { - yyerror("set-option"); // not allowed in SMT-COMP + if (!support_non_smtcomp) { + if (strcmp($3, ":produce-unsat-cores") != 0 || $4->symbol != "true") { + // not allowed in SMT-COMP + yyerror("Encountered non-SMT-COMP command: 'set-option'. Maybe you " + "want to re-run with '-support-non-smtcomp true'."); + } + delete $4; + } else { + add_node("set-option", make_node($3), $4); } - //add_node("set-option", make_node($3), $4); - /*//*/delete $4; free($3); } ; @@ -762,6 +795,80 @@ attribute : $$->set_parens_needed(false); delete $3; } +| TK_QID SYMBOL + { + // z3 + if (!support_z3) { + // not allowed in SMT-COMP + yyerror("Encountered z3-specific attribute: ':qid'. Maybe you " + "want to re-run with '-support-z3 true'."); + } + set_new_name($2); + $$ = make_node(":qid", make_name_node($2)); + $$->set_parens_needed(false); + delete $2; + } +| TK_NOPATTERN '(' term_list ')' + { + // z3 + if (!support_z3) { + // not allowed in SMT-COMP + yyerror("Encountered z3-specific attribute: ':no-pattern'. Maybe you " + "want to re-run with '-support-z3 true'."); + } + $$ = make_node(":no-pattern", make_node($3)); + $$->set_parens_needed(false); + delete $3; + } +| TK_SKOLEMID SYMBOL + { + // z3 + if (!support_z3) { + // not allowed in SMT-COMP + yyerror("Encountered z3-specific attribute: ':skolemid'. Maybe you " + "want to re-run with '-support-z3 true'."); + } + set_new_name($2); + $$ = make_node(":skolemid", make_name_node($2)); + $$->set_parens_needed(false); + delete $2; + } +| TK_LBLPOS SYMBOL + { + // z3 + if (!support_z3) { + // not allowed in SMT-COMP + yyerror("Encountered z3-specific attribute: ':lblpos'. Maybe you " + "want to re-run with '-support-z3 true'."); + } + $$ = make_node(":lblpos", make_node($2)); + $$->set_parens_needed(false); + delete $2; + } +| TK_LBLNEG SYMBOL + { + // z3 + if (!support_z3) { + // not allowed in SMT-COMP + yyerror("Encountered z3-specific attribute: ':lblneg'. Maybe you " + "want to re-run with '-support-z3 true'."); + } + $$ = make_node(":lblneg", make_node($2)); + $$->set_parens_needed(false); + delete $2; + } +| TK_WEIGHT NUMERAL + { + // z3 + if (!support_z3) { + // not allowed in SMT-COMP + yyerror("Encountered z3-specific attribute: ':weight'. Maybe you " + "want to re-run with '-support-z3 true'."); + } + $$ = make_node(":weight", make_node($2)); + $$->set_parens_needed(false); + delete $2; + } ; //////////////////////////////////////////////////////////////////////////////// diff --git a/process.non-smtcomp b/process.non-smtcomp new file mode 100755 index 0000000..f7066a4 --- /dev/null +++ b/process.non-smtcomp @@ -0,0 +1,11 @@ +#!/bin/sh + +# This is a wrapper script that allows the scrambler to be used as a +# preprocessor on StarExec. + +# $1: benchmark filename +# $2: seed + +ulimit -s 131072 +./scrambler -support-non-smtcomp true -seed "$2" < "$1" + diff --git a/process.z3 b/process.z3 new file mode 100755 index 0000000..1916bdc --- /dev/null +++ b/process.z3 @@ -0,0 +1,10 @@ +#!/bin/sh + +# This is a wrapper script that allows the scrambler to be used as a +# preprocessor on StarExec. + +# $1: benchmark filename +# $2: seed + +ulimit -s 131072 +./scrambler -support-z3 true -seed "$2" < "$1" diff --git a/scrambler.cpp b/scrambler.cpp index 3a501ab..33facbc 100644 --- a/scrambler.cpp +++ b/scrambler.cpp @@ -88,6 +88,17 @@ bool gen_ucore = false; */ bool gen_mval = false; +/* + * If set to true, support SMTLIB files that have features not supported by + * SMTCOMP + */ +bool support_non_smtcomp = false; + +/* + * If set to true, support SMTLIB files that have Z3-specific features + */ +bool support_z3 = false; + //////////////////////////////////////////////////////////////////////////////// /* @@ -821,23 +832,38 @@ void usage(const char *program) std::cout << "Syntax: " << program << " [OPTIONS] < INPUT_FILE.smt2\n" << "\n" << " -term_annot [true|false]\n" - << " controls whether term annotations are printed (default: true)\n" + << " controls whether term annotations are printed " + "(default: true)\n" << "\n" << " -seed N\n" - << " seed value (>= 0) for pseudo-random choices; if 0, no scrambling is\n" + << " seed value (>= 0) for pseudo-random choices; if 0, " + "no scrambling is\n" << " performed (default: time(0))\n" << "\n" << " -core FILE\n" - << " print only those (named) assertions whose name is contained in the\n" + << " print only those (named) assertions whose name is " + "contained in the\n" << " specified FILE (default: print all assertions)\n" << "\n" << " -gen-unsat-core [true|false]\n" - << " controls whether the output is in a format suitable for the unsat-core\n" + << " controls whether the output is in a format suitable " + "for the unsat-core\n" << " track of SMT-COMP (default: false)\n" << "\n" << " -gen-model-val [true|false]\n" - << " controls whether the output is in a format suitable for the model\n" - << " track of SMT-COMP (default: false)\n"; + << " controls whether the output is in a format suitable " + "for the model\n" + << " track of SMT-COMP (default: false)\n" + << "\n" + << " -support-non-smtcomp [true|false]\n" + << " controls whether to support SMTLIB commands that are " + "not supported\n" + << " by SMTCOMP (default: false)\n" + << "\n" + << " -support-z3 [true|false]\n" + << " controls whether to support non-SMTLIB commands that " + "are supported\n" + << " by Z3 (default: false)\n"; std::cout.flush(); exit(1); } @@ -903,6 +929,25 @@ int main(int argc, char **argv) usage(argv[0]); } i += 2; + } else if (strcmp(argv[i], "-support-non-smtcomp") == 0 && + i + 1 < argc) { + if (strcmp(argv[i + 1], "true") == 0) { + support_non_smtcomp = true; + } else if (strcmp(argv[i + 1], "false") == 0) { + support_non_smtcomp = false; + } else { + usage(argv[0]); + } + i += 2; + } else if (strcmp(argv[i], "-support-z3") == 0 && i + 1 < argc) { + if (strcmp(argv[i + 1], "true") == 0) { + support_z3 = true; + } else if (strcmp(argv[i + 1], "false") == 0) { + support_z3 = false; + } else { + usage(argv[0]); + } + i += 2; } else { usage(argv[0]); } diff --git a/test/extensions/non-smtcomp/expect/test-non-smtcomp.0.non-smtcomp.expect b/test/extensions/non-smtcomp/expect/test-non-smtcomp.0.non-smtcomp.expect new file mode 100644 index 0000000..b0d68cb --- /dev/null +++ b/test/extensions/non-smtcomp/expect/test-non-smtcomp.0.non-smtcomp.expect @@ -0,0 +1,10 @@ +(set-logic ALL) +(set-option :print-success false) +(declare-fun x () Bool) +(assert (and (not x) x)) +(check-sat) +(reset) +(declare-fun x () Bool) +(assert x) +(check-sat) +(exit) diff --git a/test/extensions/non-smtcomp/expect/test-non-smtcomp.1234.non-smtcomp.expect b/test/extensions/non-smtcomp/expect/test-non-smtcomp.1234.non-smtcomp.expect new file mode 100644 index 0000000..230336e --- /dev/null +++ b/test/extensions/non-smtcomp/expect/test-non-smtcomp.1234.non-smtcomp.expect @@ -0,0 +1,10 @@ +(set-logic ALL) +(set-option :print-success false) +(declare-fun x1 () Bool) +(assert (and x1 (not x1))) +(check-sat) +(reset) +(declare-fun x1 () Bool) +(assert x1) +(check-sat) +(exit) diff --git a/test/extensions/non-smtcomp/test-non-smtcomp.smt2 b/test/extensions/non-smtcomp/test-non-smtcomp.smt2 new file mode 100644 index 0000000..b0d68cb --- /dev/null +++ b/test/extensions/non-smtcomp/test-non-smtcomp.smt2 @@ -0,0 +1,10 @@ +(set-logic ALL) +(set-option :print-success false) +(declare-fun x () Bool) +(assert (and (not x) x)) +(check-sat) +(reset) +(declare-fun x () Bool) +(assert x) +(check-sat) +(exit) diff --git a/test/extensions/z3/expect/test-z3.0.z3.expect b/test/extensions/z3/expect/test-z3.0.z3.expect new file mode 100644 index 0000000..682c1c7 --- /dev/null +++ b/test/extensions/z3/expect/test-z3.0.z3.expect @@ -0,0 +1,15 @@ +(set-logic ALL) +(declare-sort |T@U| 0) +(declare-fun UOrdering2 (|T@U| |T@U|) Bool) +(declare-fun U_2_int (T@U) Int) +(declare-fun U_2_bool (T@U) Bool) +(declare-fun Inv0_TBitvector (T@U) Int) +(declare-fun TBitvector (Int) T@U) +(declare-fun %lbl%+0 () Bool) +(declare-fun %lbl%@1 () Bool) +(assert (forall ((x@@3 T@U)) (! (UOrdering2 x@@3 x@@3) :qid |id1| :no-pattern (U_2_int x@@3) :no-pattern (U_2_bool x@@3)))) +(assert (forall ((w Int)) (! (= (Inv0_TBitvector (TBitvector w)) w) :qid |id2| :skolemid |0| :pattern ((TBitvector w)) :weight 0))) +(assert (! (and %lbl%+0 true) :lblpos +0)) +(assert (! (or %lbl%@1 true) :lblneg @1)) +(check-sat) +(exit) diff --git a/test/extensions/z3/expect/test-z3.1234.z3.expect b/test/extensions/z3/expect/test-z3.1234.z3.expect new file mode 100644 index 0000000..8a0be1e --- /dev/null +++ b/test/extensions/z3/expect/test-z3.1234.z3.expect @@ -0,0 +1,15 @@ +(set-logic ALL) +(declare-sort x2 0) +(declare-fun x8 () Bool) +(declare-fun x5 (x2) Int) +(declare-fun x7 (Int) x2) +(declare-fun x3 (x2) Bool) +(declare-fun x10 (x2 x2) Bool) +(declare-fun x4 () Bool) +(declare-fun x1 (x2) Int) +(assert (! (or true x8) :lblneg @1)) +(assert (forall ((x11 x2)) (! (x10 x11 x11) :qid x13 :no-pattern (x5 x11) :no-pattern (x3 x11)))) +(assert (! (and x4 true) :lblpos +0)) +(assert (forall ((x12 Int)) (! (= (x1 (x7 x12)) x12) :qid x9 :skolemid x6 :pattern ((x7 x12)) :weight 0))) +(check-sat) +(exit) diff --git a/test/extensions/z3/test-z3.smt2 b/test/extensions/z3/test-z3.smt2 new file mode 100644 index 0000000..9f42070 --- /dev/null +++ b/test/extensions/z3/test-z3.smt2 @@ -0,0 +1,25 @@ +(set-logic ALL) +(set-info :smt-lib-version 2.0) +(declare-sort |T@U| 0) +(declare-fun UOrdering2 (|T@U| |T@U|) Bool) +(declare-fun U_2_int (T@U) Int) +(declare-fun U_2_bool (T@U) Bool) +(declare-fun Inv0_TBitvector (T@U) Int) +(declare-fun TBitvector (Int) T@U) +(declare-fun %lbl%+0 () Bool) +(declare-fun %lbl%@1 () Bool) +(assert (forall ((x@@3 T@U) ) (! (UOrdering2 x@@3 x@@3) + :qid |id1| + :no-pattern (U_2_int x@@3) + :no-pattern (U_2_bool x@@3) +))) +(assert (forall ((w Int) ) (! (= (Inv0_TBitvector (TBitvector w)) w) + :qid |id2| + :skolemid |0| + :pattern ( (TBitvector w)) + :weight 0 +))) +(assert (! (and %lbl%+0 true) :lblpos +0)) +(assert (! (or %lbl%@1 true) :lblneg @1)) +(check-sat) +(exit) diff --git a/test/run_tests.sh b/test/run_tests.sh index c1dde75..9a59951 100755 --- a/test/run_tests.sh +++ b/test/run_tests.sh @@ -5,6 +5,8 @@ SCRIPT_DIR=$(dirname "$(readlink -f "$0")") TESTS_SMT_COMP_DIR="${SCRIPT_DIR}/smt-comp" +TESTS_NON_SMT_COMP_DIR="${SCRIPT_DIR}/extensions/non-smtcomp" +TESTS_Z3_DIR="${SCRIPT_DIR}/extensions/z3" RED='\033[0;31m' GREEN='\033[0;32m' NOCOLOR='\033[0m' @@ -37,6 +39,12 @@ runtest() [ -d "${TESTS_SMT_COMP_DIR}" ] || die "directory '${TESTS_SMT_COMP_DIR}' does not exist" [ -d "${TESTS_SMT_COMP_DIR}/expect" ] || die "directory '${TESTS_SMT_COMP_DIR}/expect' does not exist" +[ -d "${TESTS_NON_SMT_COMP_DIR}" ] || die "directory '${TESTS_NON_SMT_COMP_DIR}' does not exist" +[ -d "${TESTS_NON_SMT_COMP_DIR}/expect" ] || die "directory '${TESTS_NON_SMT_COMP_DIR}/expect' does not exist" + +[ -d "${TESTS_Z3_DIR}" ] || die "directory '${TESTS_Z3_DIR}' does not exist" +[ -d "${TESTS_Z3_DIR}/expect" ] || die "directory '${TESTS_Z3_DIR}/expect' does not exist" + echo "Run single-query/industry challenge track scrambler..." runtest "${TESTS_SMT_COMP_DIR}" "${SCRIPT_DIR}"/../process.single-query-challenge-track 0 single runtest "${TESTS_SMT_COMP_DIR}" "${SCRIPT_DIR}"/../process.single-query-challenge-track 1234 single @@ -50,6 +58,13 @@ echo -e "\nRun model-validation track scrambler..." runtest "${TESTS_SMT_COMP_DIR}" "${SCRIPT_DIR}"/../process.model-val-track 0 model-val runtest "${TESTS_SMT_COMP_DIR}" "${SCRIPT_DIR}"/../process.model-val-track 1234 model-val +echo -e "\nRun non-SMTCOMP scrambler..." +runtest ${TESTS_NON_SMT_COMP_DIR} ${SCRIPT_DIR}/../process.non-smtcomp 0 non-smtcomp +runtest ${TESTS_NON_SMT_COMP_DIR} ${SCRIPT_DIR}/../process.non-smtcomp 1234 non-smtcomp +echo -e "\nRun Z3 scrambler..." +runtest ${TESTS_Z3_DIR} ${SCRIPT_DIR}/../process.z3 0 z3 +runtest ${TESTS_Z3_DIR} ${SCRIPT_DIR}/../process.z3 1234 z3 + if [ $exitcode -ne 0 ] then echo -e "${RED}errors occurred${NOCOLOR}"