From 85fd498d11def459e12374a875fc42ac2cb8b6cc Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Thu, 27 Feb 2025 07:29:43 -0500 Subject: [PATCH 01/22] cmd-line option: don't run sterling if off --- forge/server/forgeserver.rkt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/forge/server/forgeserver.rkt b/forge/server/forgeserver.rkt index dc2fe4ea..ce16c8f6 100644 --- a/forge/server/forgeserver.rkt +++ b/forge/server/forgeserver.rkt @@ -511,7 +511,10 @@ (printf "NO PORTS AVAILABLE. Could not start provider server.~n")) ; Now, serve the static sterling website files (this will be a different server/port). - (unless (or (equal? 'off (get-option curr-state 'run_sterling)) + ; Switch Sterling off for the "off" string too, because users may neglect the \' + ; if providing an override at the command line. This means that one cannot provide + ; a script in a file named "off". + (unless (or (member (get-option curr-state 'run_sterling) (list 'off "off" #f)) (empty? useful-run-names)) (serve-sterling-static #:provider-port port)) (when (empty? useful-run-names) From b84bf659dffb5be3eee3cce834605588231119d4 Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Thu, 27 Feb 2025 07:51:01 -0500 Subject: [PATCH 02/22] cleanup: minor cleanup --- forge/sigs-functional.rkt | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/forge/sigs-functional.rkt b/forge/sigs-functional.rkt index e7044847..294fb68e 100644 --- a/forge/sigs-functional.rkt +++ b/forge/sigs-functional.rkt @@ -2,7 +2,10 @@ ; Functional interface to the Forge library and solver. ; Formula/expression macros should largely be kept in sigs.rkt instead. -; The design intent is: forge -> forge/core (in sigs.rkt) -> functional forge (this module) +; The design intent is: +; * forge surface languages use -> +; * forge/core (in sigs.rkt) uses -> +; * functional forge (this module) ;; TODO: there is still some duplicate logic (+ importing?) between this module + sigs, and possibly ;; still unused imports... @@ -57,10 +60,7 @@ (provide let quote) ; ; Technical stuff -; (provide set-verbosity VERBOSITY_LOW VERBOSITY_HIGH) -; (provide set-path!) (provide set-option!) -; (define (set-path! path) #f) ; ; Data structures (provide (prefix-out forge: (struct-out Sig)) @@ -82,14 +82,6 @@ ; Don't prefix with tree:, that's already been done when importing (provide (all-from-out forge/utils/lazy-tree)) -; ; Export everything for doing scripting -; (provide (prefix-out forge: (all-defined-out))) -; (provide (prefix-out forge: (struct-out bound))) -; (provide (prefix-out forge: relation-name)) - -; (provide (struct-out Sat) -; (struct-out Unsat)) - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Language-Specific Checks ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -376,8 +368,6 @@ [(node/expr/op/~ info arity (list left-rel)) (break left-rel (get-co right))] [_ (fail "is")]) - ; hopefully the above calls to break update these somehow - ; and hopefully they don't rely on state :( (values scope bound)] ; Other instances (which may add new scope, bound, piecewise-bound information) @@ -446,9 +436,6 @@ (values scope (update-piecewise-binds 'ni the-relation the-atom left))] ; anything else is unexpected [else (fail "rel in/ni")])] - - ; Bitwidth - ; what does (Int n:nat) look like in the AST? [_ (fail "Invalid binding expression")])) From 5d6c27db10ce286eb596c55b937eabff96029417 Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Thu, 27 Feb 2025 12:03:13 -0500 Subject: [PATCH 03/22] add: test case for pred->fun/fun->pred recursive --- forge/tests/forge/other/recursive-error.frg | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/forge/tests/forge/other/recursive-error.frg b/forge/tests/forge/other/recursive-error.frg index c126a9f6..363869d9 100644 --- a/forge/tests/forge/other/recursive-error.frg +++ b/forge/tests/forge/other/recursive-error.frg @@ -53,7 +53,9 @@ fun h[a: A]: one A { h[a] } fun f[a: A]: one A { g[a] } fun g[a: A]: one A { f[a] } - +// cycle between a function and a predicate +fun i[a: A]: one A { some {b: A | j[b]} } +pred j[a: A] { some i[a] } @@ -73,4 +75,7 @@ test expect { recur_fun_2loop: {some a: A | f[a]} is forge_error "f eventually called itself" recur_fun_self: {some a: A | h[a]} is forge_error "h eventually called itself" + + recur_pred_fun: {some a: A | j[a]} is forge_error "j eventually called itself" + recur_fun_pred: {some a: A | some i[a]} is forge_error "i eventually called itself" } \ No newline at end of file From 688ea1f5e3561d012c3dc9a50b2306b32f90c23b Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Tue, 25 Mar 2025 09:26:08 -0400 Subject: [PATCH 04/22] [patch] Handle spaces and quotes in filenames w.r.t. run IDs on backend (#302) * fix: handle spaces and quotes in forge filenames w.r.t. run IDs * windows-specific test scripting * add to gitignore * remote temp file * fix for windows --- .gitignore | 2 ++ forge/lang/expander.rkt | 25 ++++++++++++------ forge/run-tests.sh | 26 +++++++++++++++++++ forge/tests/forge/other/QUOTES_TEMPLATE.txt | 8 ++++++ forge/tests/forge/other/Space In Filename.frg | 8 ++++++ 5 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 forge/tests/forge/other/QUOTES_TEMPLATE.txt create mode 100644 forge/tests/forge/other/Space In Filename.frg diff --git a/.gitignore b/.gitignore index 77a35010..4c14512b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ forge/kodkod-cli/out/ forge/pardinus-cli/out forge/pardinus-cli/classes *.icloud + +*quotes_in_*filename.frg \ No newline at end of file diff --git a/forge/lang/expander.rkt b/forge/lang/expander.rkt index b750c711..362a9af9 100644 --- a/forge/lang/expander.rkt +++ b/forge/lang/expander.rkt @@ -6,7 +6,8 @@ (require syntax/parse/define racket/stxparam (for-syntax racket/base syntax/parse racket/syntax syntax/parse/define racket/function syntax/srcloc racket/match racket/list - (only-in racket/path file-name-from-path)) + (only-in racket/path file-name-from-path) + (only-in racket/string string-replace)) syntax/srcloc ; Needed because the abstract-tok definition below requires phase 2 (for-syntax (for-syntax racket/base))) @@ -971,16 +972,24 @@ (define-for-syntax make-temporary-name (let ((name-counter (box 1))) (lambda (stx) + ; A run name cannot have empty space in it, yet a filename might. + ; (Requires "pre compiled regexp" #px to use \s) + (define (scrub s) + (let* ([no_blanks (string-replace s #px"\\s" "_" #:all? #t)] + [no_sq (string-replace no_blanks #px"'" "SQ" #:all? #t)] + [no_dq (string-replace no_sq #px"\"" "DQ" #:all? #t)]) + no_dq)) (define curr-num (unbox name-counter)) (set-box! name-counter (+ 1 curr-num)) (define source_disambiguator - (cond [(and (source-location-source stx) - (or (path-string? (source-location-source stx)) - (path-for-some-system? (source-location-source stx))) - (file-name-from-path (source-location-source stx))) - (path-replace-extension (file-name-from-path (source-location-source stx)) #"")] - [(symbol? (source-location-source stx)) (symbol->string (source-location-source stx))] - [else "unknown"])) + (scrub + (cond [(and (source-location-source stx) + (or (path-string? (source-location-source stx)) + (path-for-some-system? (source-location-source stx))) + (file-name-from-path (source-location-source stx))) + (path-element->string (path-replace-extension (file-name-from-path (source-location-source stx)) #""))] + [(symbol? (source-location-source stx)) (symbol->string (source-location-source stx))] + [else "unknown"]))) (string->symbol (format "temporary-name_~a_~a" source_disambiguator curr-num))))) ; CmdDecl : (Name /COLON-TOK)? (RUN-TOK | CHECK-TOK) Parameters? (QualName | Block)? Scope? (/FOR-TOK Bounds)? diff --git a/forge/run-tests.sh b/forge/run-tests.sh index 891c7919..d41eee18 100755 --- a/forge/run-tests.sh +++ b/forge/run-tests.sh @@ -20,6 +20,8 @@ testDir=$1 #doNotTestPattern="\(error\|srclocs\)/[^/]*\\.frg" doNotTestPattern="\(error\|srclocs\)/.*\\.frg" # ^ these tests get checked by tests/error/main.rkt + +# This will create a newline-separated list of file names. But note comments on `for` below. testFiles="$( find $testDir -type f \( -name "*.rkt" -o -name "*.frg" \) | grep --invert-match ${doNotTestPattern} )" numTestFiles="$(echo "$testFiles" | wc -l)" @@ -31,6 +33,10 @@ exitCode=0 echo -e "Found the following $numTestFiles test files:\n$breakLine$testFiles\n$breakLine" # Run tests and report progress +# Default bash `for` will word-split on blank space only, ignoring the quotes added above. +# So we set the "internal field separator" and then reset it after the loop. +IFS=' +' for testFile in $testFiles; do current=`date "+%X"` echo -e "\nRunning $testFile ($current)" @@ -48,4 +54,24 @@ for testFile in $testFiles; do fi done +# Windows disallows quotes in a filename, but Linux and MacOS permit it. +# To test that Forge is properly handling these without breaking the +# test suite on Windows, we create the file dynamically based on OS. +# If running from Git Bash, uname will return a different value. +osid=$(uname) +if [[ osid != "Windows" && ![[osid =~ ^MINGW]] ]]; then + echo "Creating file with quotes in its name..." + touch "$testDir/forge/other/quotes_in_\"_'_filename.frg" + cat "$testDir/forge/other/QUOTES_TEMPLATE.txt" > "$testDir/forge/other/quotes_in_\"_'_filename.frg" + + racket "$testDir/forge/other/quotes_in_\"_'_filename.frg" -O run_sterling \'off > /dev/null + testExitCode=$? + if [[ $testExitCode -ne 0 ]]; then + echo "Test failed with code $testExitCode" + exitCode=1 + fi + rm "$testDir/forge/other/quotes_in_\"_'_filename.frg" +else + echo "Windows forbids files with quotes in their name; skipping that test..." +fi exit $exitCode diff --git a/forge/tests/forge/other/QUOTES_TEMPLATE.txt b/forge/tests/forge/other/QUOTES_TEMPLATE.txt new file mode 100644 index 00000000..9195f031 --- /dev/null +++ b/forge/tests/forge/other/QUOTES_TEMPLATE.txt @@ -0,0 +1,8 @@ +#lang forge + +/* + Confirm that Forge's test runner can handle quotes and single-quotes in filenames. +*/ + +option verbose 5 +assert {} is sat \ No newline at end of file diff --git a/forge/tests/forge/other/Space In Filename.frg b/forge/tests/forge/other/Space In Filename.frg new file mode 100644 index 00000000..f6b7e987 --- /dev/null +++ b/forge/tests/forge/other/Space In Filename.frg @@ -0,0 +1,8 @@ +#lang forge + +/* + Confirm that Forge's default run names are properly substituting blank space + in the model file name. +*/ + +assert {} is sat \ No newline at end of file From 8a0e270548ac9857b0a9fa5fe70bd2e551044a69 Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Fri, 25 Apr 2025 08:46:06 -0400 Subject: [PATCH 05/22] Feat int minimization (#303) Merging integer/set optimization into dev branch. --- forge/lang/alloy-syntax/lexer.rkt | 7 +- forge/lang/alloy-syntax/parser.rkt | 10 +- forge/lang/expander.rkt | 41 ++- forge/run-tests.sh | 72 ++++- forge/send-to-solver.rkt | 12 +- forge/server/eval-model.rkt | 21 +- forge/server/modelToXML.rkt | 8 +- forge/sigs-functional.rkt | 62 ++++- forge/sigs-structs.rkt | 22 +- forge/sigs.rkt | 68 +++-- forge/solver-specific/pardinus.rkt | 6 +- forge/tests/forge/target/close_fixed.frg | 15 - .../tests/forge/target/close_retargeting.frg | 16 -- forge/tests/forge/target/far_fixed.frg | 16 -- forge/tests/forge/target/far_retargeting.frg | 17 -- forge/tests/forge/target/hamming_runs.frg | 12 - forge/tests/forge/target/tomf.frg | 151 ++++++++++ forge/tests/forge/target/tomf.rkt | 261 ++++++++++++++++++ forge/tests/forge/target/tomf_change.frg | 74 +++++ forge/utils/collector.rkt | 12 +- forge/utils/target-oriented.rkt | 183 ++++++++++++ 21 files changed, 943 insertions(+), 143 deletions(-) delete mode 100644 forge/tests/forge/target/close_fixed.frg delete mode 100644 forge/tests/forge/target/close_retargeting.frg delete mode 100644 forge/tests/forge/target/far_fixed.frg delete mode 100644 forge/tests/forge/target/far_retargeting.frg delete mode 100644 forge/tests/forge/target/hamming_runs.frg create mode 100644 forge/tests/forge/target/tomf.frg create mode 100644 forge/tests/forge/target/tomf.rkt create mode 100644 forge/tests/forge/target/tomf_change.frg create mode 100644 forge/utils/target-oriented.rkt diff --git a/forge/lang/alloy-syntax/lexer.rkt b/forge/lang/alloy-syntax/lexer.rkt index ced8a731..383ab470 100644 --- a/forge/lang/alloy-syntax/lexer.rkt +++ b/forge/lang/alloy-syntax/lexer.rkt @@ -123,7 +123,12 @@ ["break" (token+ `BREAK-TOK "" lexeme "" lexeme-start lexeme-end)] ["sufficient" (token+ `SUFFICIENT-TOK "" lexeme "" lexeme-start lexeme-end)] ["necessary" (token+ `NECESSARY-TOK "" lexeme "" lexeme-start lexeme-end)] - ["suite" (token+ `SUITE-TOK "" lexeme "" lexeme-start lexeme-end)] + ["suite" (token+ `SUITE-TOK "" lexeme "" lexeme-start lexeme-end)] + + ; Target orientation + ["minimize_int" (token+ `MINIMIZE_INT-TOK "" lexeme "" lexeme-start lexeme-end)] + ["maximize_int" (token+ `MAXIMIZE_INT-TOK "" lexeme "" lexeme-start lexeme-end)] + ["target_pi" (token+ `TARGET_PI-TOK "" lexeme "" lexeme-start lexeme-end)] ;["state" (token+ `STATE-TOK "" lexeme "" lexeme-start lexeme-end)] ;["facts" (token+ `STATE-TOK "" lexeme "" lexeme-start lexeme-end)] diff --git a/forge/lang/alloy-syntax/parser.rkt b/forge/lang/alloy-syntax/parser.rkt index 93a50b14..978c3415 100644 --- a/forge/lang/alloy-syntax/parser.rkt +++ b/forge/lang/alloy-syntax/parser.rkt @@ -84,9 +84,15 @@ FunDecl : /FUN-TOK (QualName DOT-TOK)? Name ParaDecls? /COLON-TOK HelperMult? Ex ParaDecls : /LEFT-PAREN-TOK @ParaDeclList? /RIGHT-PAREN-TOK | /LEFT-SQUARE-TOK @ParaDeclList? /RIGHT-SQUARE-TOK +; Configure target-oriented model finding, or integer optimization (which builds on TOMF). +; Expect the type of targeted search, followed by the target, and then the mode (optionally). +TOMFParams : TARGET_PI-TOK Bounds + | MINIMIZE_INT-TOK Block + | MAXIMIZE_INT-TOK Block + AssertDecl : /ASSERT-TOK Name? Block -CmdDecl : Name /COLON-TOK (RUN-TOK | CHECK-TOK) (QualName | Block)? Scope? (/FOR-TOK Bounds)? - | (RUN-TOK | CHECK-TOK) (QualName | Block)? Scope? (/FOR-TOK Bounds)? +CmdDecl : Name /COLON-TOK (RUN-TOK | CHECK-TOK) (QualName | Block)? Scope? (/FOR-TOK Bounds)? (TOMFParams)? + | (RUN-TOK | CHECK-TOK) (QualName | Block)? Scope? (/FOR-TOK Bounds)? (TOMFParams)? TestDecl : (Name /COLON-TOK)? (QualName | Block) Scope? (/FOR-TOK Bounds)? /IS-TOK (SAT-TOK | UNSAT-TOK | UNKNOWN-TOK | THEOREM-TOK | FORGE_ERROR-TOK (PATH-OR-STR-TOK)? | CHECKED-TOK ) diff --git a/forge/lang/expander.rkt b/forge/lang/expander.rkt index 362a9af9..1dc94294 100644 --- a/forge/lang/expander.rkt +++ b/forge/lang/expander.rkt @@ -9,6 +9,7 @@ (only-in racket/path file-name-from-path) (only-in racket/string string-replace)) syntax/srcloc + (only-in racket/list flatten) ; Needed because the abstract-tok definition below requires phase 2 (for-syntax (for-syntax racket/base))) @@ -327,7 +328,8 @@ (~optional (~or pred-name:QualNameClass pred-block:BlockClass)) (~optional scope:ScopeClass) - (~optional bounds:BoundsClass)))) + (~optional bounds:BoundsClass) + (~optional tomf:TOMFClass)))) ; TestDecl : (Name /COLON-TOK)? Parameters? (QualName | Block)? Scope? (/FOR-TOK Bounds)? /IS-TOK (SAT-TOK | UNSAT-TOK) (define-syntax-class TestDeclClass @@ -720,6 +722,34 @@ (~optional (~or "lone" "some" "one" "two" "set")))) (pattern ((~datum ArrowOp) "*"))) + ; TOMF annotation on a `run` + (define-syntax-class TOMFClass + (pattern ((~datum TOMFParams) + (~datum "target_pi") + tgt_b:BoundsClass) + ; This syntax takes the same form as a partial-instance block. These may refer to other + ; instance blocks, so the dependencies need to be resolved by `make-inst`. The resulting + ; Inst struct then needs to be converted to inst-hash format. (The restriction that the + ; partial instance be exact-bounds only is checked by the final conversion step, which + ; is done in sigs-functional.) + #:attr translate_tgt #`(make-inst (flatten (list #,@#'tgt_b.translate))) + #:attr translate_mode #'close_noretarget) + + ; The syntax for int optimization doesn't expect a partial instance, but rather a + ; {}-delimited integer expression. + (pattern ((~datum TOMFParams) + (~datum "minimize_int") + tgt_ie:BlockClass) + #:attr translate_tgt #'tgt_ie + #:attr translate_mode #'close_noretarget) + + (pattern ((~datum TOMFParams) + (~datum "maximize_int") + tgt_ie:BlockClass) + #:attr translate_tgt #'tgt_ie + #:attr translate_mode #'far_noretarget) ) + + ; CompareOp : IN-TOK | EQ-TOK | LT-TOK | GT-TOK | LEQ-TOK | GEQ-TOK | EQUIV-TOK | IS-TOK | NI-TOK (define-syntax-class CompareOpClass (pattern ((~datum CompareOp) @@ -786,7 +816,6 @@ exprs:ExprClass ...)))) - ; AlloyModule : ModuleDecl? Import* Paragraph* ; | EvalDecl* (define-syntax (AlloyModule stx) @@ -1001,16 +1030,20 @@ (~optional (~or pred:QualNameClass preds:BlockClass)) (~optional scope:ScopeClass) - (~optional bounds:BoundsClass)) + (~optional bounds:BoundsClass) + (~optional tomf:TOMFClass)) (with-syntax ([cmd-type (datum->syntax #'cmd-type (string->symbol (syntax->datum #'cmd-type)) #'cmd-type)] [name #`(~? name.name #,(make-temporary-name stx))] [preds #'(~? pred.name preds)]) + ;(printf "Trying to make target: ~a~n" #'tomf.translate_tgt) #`(begin #,(syntax/loc stx (cmd-type name (~? (~@ #:preds [preds])) (~? (~@ #:scope scope.translate)) - (~? (~@ #:bounds bounds.translate)))) + (~? (~@ #:bounds bounds.translate)) + (~? (~@ #:target tomf.translate_tgt)) + (~? (~@ #:target-distance tomf.translate_mode)))) ; This should no longer be called per-command. Instead, an external coordinator ; (such as Sterling) will say when (and if) each command should be executed. ;#,(syntax/loc stx (display name)) diff --git a/forge/run-tests.sh b/forge/run-tests.sh index d41eee18..05e00baf 100755 --- a/forge/run-tests.sh +++ b/forge/run-tests.sh @@ -21,6 +21,8 @@ testDir=$1 doNotTestPattern="\(error\|srclocs\)/.*\\.frg" # ^ these tests get checked by tests/error/main.rkt +smtTestPattern=".*/smtlibtor/.*" + # This will create a newline-separated list of file names. But note comments on `for` below. testFiles="$( find $testDir -type f \( -name "*.rkt" -o -name "*.frg" \) | grep --invert-match ${doNotTestPattern} )" numTestFiles="$(echo "$testFiles" | wc -l)" @@ -32,6 +34,19 @@ exitCode=0 # Print header of test files found echo -e "Found the following $numTestFiles test files:\n$breakLine$testFiles\n$breakLine" +########################## +# Run the given test suite +########################## + +which cvc5 &> /dev/null; +cvc5OnPathES=$? + +if [[ $cvc5OnPathES -eq 0 ]]; then + echo "Found cvc5, will run SMT tests if any." +else + echo "Could not find cvc5, will skip SMT tests if any." +fi + # Run tests and report progress # Default bash `for` will word-split on blank space only, ignoring the quotes added above. # So we set the "internal field separator" and then reset it after the loop. @@ -39,28 +54,47 @@ IFS=' ' for testFile in $testFiles; do current=`date "+%X"` - echo -e "\nRunning $testFile ($current)" + [[ $testFile =~ ${smtTestPattern} ]] + matchedSMT=$? - #start=`date +%s` - # Use permanent (-O) option flag to always disable Sterling - racket $testFile -O run_sterling \'off > /dev/null - #end=`date +%s` - #echo -e "Testfile took $((end-start)) seconds." - testExitCode=$? + echo -e -n "\nRunning $testFile ($current)" + if [[ $matchedSMT -eq 0 ]]; then + echo " (smt)" + else + echo " " + fi + + # Only run SMT tests if cvc5 is on the path. + if [[ $cvc5OnPathES != 0 && $matchedSMT -eq 0 ]]; then + echo "Skipping SMT backend test because cvc5 is not on the PATH: $testFile" + else + #start=`date +%s` + # Use permanent (-O) option flag to always disable Sterling + racket $testFile -O run_sterling \'off > /dev/null + #end=`date +%s` + #echo -e "Testfile took $((end-start)) seconds." + testExitCode=$? + fi if [[ $testExitCode -ne 0 ]]; then echo "Test failed with code $testExitCode" exitCode=1 fi -done +done + +##################################### +# Check for unusual filename handling +##################################### # Windows disallows quotes in a filename, but Linux and MacOS permit it. # To test that Forge is properly handling these without breaking the # test suite on Windows, we create the file dynamically based on OS. # If running from Git Bash, uname will return a different value. osid=$(uname) -if [[ osid != "Windows" && ![[osid =~ ^MINGW]] ]]; then - echo "Creating file with quotes in its name..." +if [[ "$testDir" != "tests" ]]; then + echo "Skipping unusual filename handling, as script was run on a subdirectory of the tests directory." +elif [[ $(uname) != "Windows" && ! $(uname) =~ ^MINGW ]]; then + echo "Testing unusual filename handling: creating file with quotes in its name..." touch "$testDir/forge/other/quotes_in_\"_'_filename.frg" cat "$testDir/forge/other/QUOTES_TEMPLATE.txt" > "$testDir/forge/other/quotes_in_\"_'_filename.frg" @@ -72,6 +106,22 @@ if [[ osid != "Windows" && ![[osid =~ ^MINGW]] ]]; then fi rm "$testDir/forge/other/quotes_in_\"_'_filename.frg" else - echo "Windows forbids files with quotes in their name; skipping that test..." + echo "Windows (uname = $osid) forbids files with quotes in their name; skipping that test..." fi exit $exitCode + + +# Notes on bash scripting: +# * when using [[ ... ]]; in an if-statement, there must be spaces between the +# ... and the brackets. This is because of how bash tokenizes by blank space. +# +# * the conditional of an if-statement is about exit status. So sometimes you +# can use a command directly, without brackets. But use of brackets forms a +# combined command. See the "test" command, e.g., +# test 1 = 1 +# echo $? +# test 1 = 2 +# echo $? +# While `test` implements [ ], double-brackets are extended syntax. Try: +# [[ "food" =~ "foo" ]] ; echo $? + diff --git a/forge/send-to-solver.rkt b/forge/send-to-solver.rkt index 09aa2ba9..0c468a77 100644 --- a/forge/send-to-solver.rkt +++ b/forge/send-to-solver.rkt @@ -28,7 +28,7 @@ ; Disable DrRacket GUI extension/tool ;(require "drracket-gui.rkt") -(provide send-to-solver) +(provide send-to-solver reset-run-name-history! stop-solver-process!) (define no-version-printed-yet #t) @@ -41,6 +41,14 @@ ; In order to prevent a bad crash, keep track of run-names used in the past, ; and throw a friendlier error if one is re-used. (define run-name-history (box (list))) +(define (reset-run-name-history!) + (set-box! run-name-history (list))) + +; This function is provided for scripting tests, but it is volatile; don't rely on it. +(define (stop-solver-process!) + (when (unbox server-state) + ((Server-ports-shutdown (unbox server-state))) + (set-box! server-state #f))) ; send-to-solver :: Run-spec -> Stream, List ; Given a Run-spec structure, processes the data and communicates it to KodKod-CLI; @@ -161,7 +169,7 @@ ; Initializing our backend process, and getting ports for communication with it. ; This was originally just Kodkod; some of that terminology remains. (define backend (get-option run-spec 'backend)) - (define-values (stdin stdout stderr shutdown is-running?) + (define-values (stdin stdout stderr shutdown is-running?) (cond ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; if there is an active server state, and the server is running diff --git a/forge/server/eval-model.rkt b/forge/server/eval-model.rkt index 13f93ea4..a8f7fcac 100644 --- a/forge/server/eval-model.rkt +++ b/forge/server/eval-model.rkt @@ -2,17 +2,18 @@ ; NOTE WELL: this module is not used in the Sterling evaluator anymore. ; Instead, Forge uses it for evaluating expressions in `inst` bounds. +; It may also be used to aid in writing forge/core tests. (require racket/match - (only-in "../lang/ast.rkt" relation-name raise-forge-error) racket/hash + racket/struct + syntax/srcloc (only-in racket range take first second rest flatten empty remove-duplicates string-join empty? set->list list->set set-subtract set-intersect)) -(require (prefix-in ast: "../lang/ast.rkt")) -(require "../shared.rkt") -(require racket/struct) (require (only-in racket/base [abs racket-abs])) -(require syntax/srcloc) + +(require forge/shared + (prefix-in ast: forge/lang/ast)) (provide eval-exp eval-unknown eval-int-expr model->binding) (provide int-atom int-atom->string int-atom? int-atom-n ->string) @@ -47,7 +48,7 @@ (define (model->binding model bitwidth) (define out-bind (make-hash)) (hash-map model (lambda (k v) (hash-set! out-bind - (string->symbol (relation-name k)) + (string->symbol (ast:relation-name k)) (ints-to-atoms v)))) ; add Int relation to our binding with appropriate bitwidth @@ -77,7 +78,7 @@ ; (This is a useful function to keep around, even if Sterling calls Kodkod's evaluator now.) (define (eval-unknown thing bind bitwidth) (define (final-fallback t b bw) - (raise-forge-error #:msg "Not a formula, expression, or int expression" + (ast:raise-forge-error #:msg "Not a formula, expression, or int expression" #:context t)) ((try-eval eval-int-expr (try-eval eval-exp final-fallback)) thing bind bitwidth)) @@ -168,7 +169,7 @@ [id (cond [(relation? id) - (raise-forge-error #:msg "Implicit set comprehension is disallowed - use \"set\"" + (ast:raise-forge-error #:msg "Implicit set comprehension is disallowed - use \"set\"" #:context id)] ; relation name, and we have an entry in the binding: extract the value [(hash-has-key? bind id) (hash-ref bind id)] @@ -178,9 +179,9 @@ ; Otherwise, If this is an unsafe evaluation, just return the value [(not safe) id] ; Otherwise, if this is a safe evaluation, throw an error - [else (raise-forge-error #:msg (format "Value of expression ~a is not defined in this context." id) + [else (ast:raise-forge-error #:msg (format "Value of expression ~a is not defined in this context." id) #:context id)])] - [_ (raise-forge-error #:msg "Not a supported expression for Racket-side evaluation" + [_ (ast:raise-forge-error #:msg "Not a supported expression for Racket-side evaluation" #:context exp)])) ; The result represents a set of tuples, so ensure proper formatting and duplicate elimination diff --git a/forge/server/modelToXML.rkt b/forge/server/modelToXML.rkt index 5134d2f1..8bf3bc27 100644 --- a/forge/server/modelToXML.rkt +++ b/forge/server/modelToXML.rkt @@ -267,7 +267,8 @@ here-string-delimiter (define sigs-unsorted (filter (λ (key) (and (equal? (relation-arity key) 1) (not (equal? (relation-name key) "Int")) - (not (string-prefix? (relation-name key) "$")))) + (not (string-prefix? (relation-name key) "$")) + (not (string-prefix? (relation-name key) "__")))) (hash-keys data))) (define skolems (filter (lambda (key) (string-prefix? (relation-name key) "$")) (hash-keys data))) @@ -334,7 +335,10 @@ here-string-delimiter ; RACKET "or" (define fields (filter-not (λ (key) (or (equal? (relation-arity key) 1) - (string-prefix? (relation-name key) "$"))) + ; Skolem relations (which may have arity >1) + (string-prefix? (relation-name key) "$") + ; Helper relations added internally + (string-prefix? (relation-name key) "__"))) (hash-keys data))) (define sigs# (length sigs)) diff --git a/forge/sigs-functional.rkt b/forge/sigs-functional.rkt index 294fb68e..7ac14f28 100644 --- a/forge/sigs-functional.rkt +++ b/forge/sigs-functional.rkt @@ -16,7 +16,8 @@ (only-in racket/function thunk) (only-in racket/math nonnegative-integer?) (only-in racket/list first second range rest empty flatten) - (only-in racket/set list->set set->list set-union set-intersect subset? set-count)) + (only-in racket/set list->set set->list set-union set-intersect subset? set-count) + (only-in racket/hash hash-union)) (require (only-in syntax/srcloc build-source-location-syntax)) (require (except-in forge/lang/ast ->) @@ -46,7 +47,8 @@ display) (provide Int succ) (provide (prefix-out forge: make-model-generator)) -(provide solution-diff) +(provide solution-diff) +(provide reset-run-name-history! stop-solver-process!) ; ; Instance analysis functions ; (provide is-sat? is-unsat?) @@ -617,8 +619,62 @@ (unless (node/formula? p) (raise-forge-error #:msg (format "Expected a formula but got something else: ~a" (deparse p)) #:context command))) + + (define (inst->hash/exact tgt-i) + (define-values (tgt-scope tgt-bounds) + ((Inst-func tgt-i) scope-with-ones default-bounds)) + + (unless (hash-empty? (Bound-piecewise tgt-bounds)) + (raise-forge-error #:msg (format "Piecewise bounds are not allowed in target. Use `R = ...`") + #:context command)) + (define tbhash + (for/hash ([rel (hash-keys (Bound-tbindings tgt-bounds))] + ; remove built-ins + #:unless (member (string->symbol (node/expr/relation-name rel)) '(Int succ))) + (define val (hash-ref (Bound-tbindings tgt-bounds) rel)) + (define relname (string->symbol (node/expr/relation-name rel))) + (values relname (map (lambda (tup) + (map (lambda (atom) + (if (int-atom? atom) + (int-atom-n atom) + atom)) + tup)) val)))) + (define pbhash + (for/hash ([rel (hash-keys (Bound-pbindings tgt-bounds))]) + (define val (hash-ref (Bound-pbindings tgt-bounds) rel)) + (define relname (string->symbol (node/expr/relation-name rel))) + (define lower (sbound-lower val)) + (define upper (sbound-upper val)) + (unless (equal? lower upper) + (raise-forge-error #:msg (format "Non-exact bounds on ~a are not allowed in target. Use `=`, not `in` or `ni`." relname) + #:context command)) + (values relname (map (lambda (tup) + (map (lambda (atom) + (if (int-atom? atom) + (int-atom-n atom) + atom)) + tup)) (set->list lower))))) + + (hash-union tbhash pbhash + #:combine/key (lambda (k v1 v2) + (unless (equal? v1 v2) + (raise-forge-error #:msg (format"Error with the provided target bounds: generation was both total and partial for relation ~a" k) + #:context command)) + v1))) + + + + (define cleaned-target + (cond [(and target (Inst? (Target-target target))) + ; Rebuild as a hash-based instance + (Target + (inst->hash/exact (Target-target target)) + (Target-distance target))] + [else + target])) + ;(printf "cleaned-target: ~a~n" cleaned-target) - (define spec (Run-spec state preds scope bounds-with-piecewise-lower target)) + (define spec (Run-spec state preds scope bounds-with-piecewise-lower cleaned-target)) (define-values (result atoms server-ports kodkod-currents kodkod-bounds) (send-to-solver spec command #:run-name name)) diff --git a/forge/sigs-structs.rkt b/forge/sigs-structs.rkt index 0690037d..7c1c2cbb 100644 --- a/forge/sigs-structs.rkt +++ b/forge/sigs-structs.rkt @@ -150,7 +150,11 @@ ; A Target describes the goal of a target-oriented model-finding run. (struct/contract Target ( - [instance (hash/c symbol? (listof (listof symbol?)))] + [target (or/c + ; Original forge/core partial-instance notation + (hash/c symbol? (listof (listof (or/c number? symbol?)))) + ; `inst` notation from #lang forge + Inst?)] ; This is not the same as option target_mode, which provides a global default. ; Rather, this is per target. [distance (or/c 'close_noretarget 'far_noretarget 'close_retarget 'far_retarget 'hamming_cover)] @@ -254,7 +258,7 @@ ; an engine_verbosity of 1 logs SEVERE level in the Java engine; ; this will send back info about crashes, but shouldn't spam (and possibly overfill) stderr. (define DEFAULT-OPTIONS (Options 'surface 'SAT4J 'pardinus 20 0 0 1 5 'default - 'close-noretarget 'fast 0 'off 'on 0 1 'first 'false #f)) + 'close_noretarget 'fast 0 'off 'on 0 1 'first 'false #f)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;; Constants ;;;;;;; @@ -424,8 +428,11 @@ Returns whether the given run resulted in sat or unsat, respectively. (Sig-name sig-name-or-rel)] [(node/expr/relation? sig-name-or-rel) (string->symbol (relation-name sig-name-or-rel))] - [else (error (format "get-sig failed to locate: ~a" sig-name-or-rel))])) - (hash-ref (State-sigs (get-state run-or-state)) sig-name)) + [else (raise-forge-error #:msg (format "get-sig failed to locate: ~a" sig-name-or-rel) + #:context #f)])) + (cond [(hash-has-key? (State-sigs (get-state run-or-state)) sig-name) + (hash-ref (State-sigs (get-state run-or-state)) sig-name)] + [else #f])) ; get-sigs :: Run-or-State, Relation*? -> List ; If a relation is provided, returns the column sigs; @@ -464,7 +471,9 @@ Returns whether the given run resulted in sat or unsat, respectively. (string->symbol (relation-name relation-name-or-rel))] [(Relation? relation-name-or-rel) (Relation-name relation-name-or-rel)])) - (hash-ref (State-relations (get-state run-or-state)) name)) + (cond [(hash-has-key? (State-relations (get-state run-or-state)) name) + (hash-ref (State-relations (get-state run-or-state)) name)] + [else #f])) ; get-relations :: Run-or-State -> List ; Returns the Relations in a run/state. @@ -870,8 +879,9 @@ Returns whether the given run resulted in sat or unsat, respectively. (if (member (get-option (get-run-spec run-or-state) 'backend) UNBOUNDED_INT_BACKENDS) (remove-duplicates (flatten (map (lambda (n) (primify run-or-state n)) (remove 'Int (map Sig-name (get-sigs run-or-state)))))) (remove-duplicates (flatten (map (lambda (n) (primify run-or-state n)) (cons 'Int (map Sig-name (get-sigs run-or-state)))))))] - [else + [else (define the-sig (get-sig run-or-state signame)) + (define all-primitive-descendants (remove-duplicates (flatten diff --git a/forge/sigs.rkt b/forge/sigs.rkt index 505b8287..c8615f70 100644 --- a/forge/sigs.rkt +++ b/forge/sigs.rkt @@ -15,7 +15,8 @@ (require forge/shared) (require forge/lang/ast forge/lang/bounds - forge/breaks) + forge/breaks + forge/utils/target-oriented) (require (only-in forge/lang/reader [read-syntax read-surface-syntax])) (require forge/server/eval-model) (require forge/server/forgeserver) @@ -39,7 +40,9 @@ check-from-state make-check test-from-state - make-test)) + make-test + reset-run-name-history! + stop-solver-process!)) (require forge/choose-lang-specific) ; Commands @@ -95,7 +98,9 @@ check-from-state make-check test-from-state - make-test) + make-test + reset-run-name-history! + stop-solver-process!) ; Export everything for doing scripting (provide (prefix-out forge: (all-defined-out))) @@ -127,7 +132,8 @@ (raise-user-error (format "tried to add sig ~a, but it already existed" name))) ;(define new-sig (Sig name rel one abstract extends)) (when (and extends (not (member extends (State-sig-order state)))) - (raise-user-error "Can't extend nonexistent sig.")) + (raise-user-error (format "Can't extend nonexistent sig ~a. Options were: ~a" + extends (State-sig-order state)))) (define new-state-sigs (hash-set (State-sigs state) name new-sig)) (define new-state-sig-order (append (State-sig-order state) (list name))) @@ -292,7 +298,7 @@ ; The environment threaded through commands (define curr-state init-state) -(define (update-state! new-state) +(define (update-state! new-state) (set! curr-state new-state)) ; check-temporal-for-var :: Boolean String -> void @@ -633,41 +639,68 @@ (~optional (~seq #:scope ((sig:id (~optional lower:nat) upper:nat) ...))) (~optional (~or (~seq #:bounds (boundss ...)) (~seq #:bounds bound))) + (~optional (~seq #:solver solver-choice)) ;unused (~optional (~seq #:backend backend-choice)) ;unused - (~optional (~seq #:target target-instance)) - ;the last 3 appear to be unused in functional forge + + ; In forge/functional, these 2 options are passed together as part of a Target struct. + (~optional (~seq #:target target-pi-or-int)) (~optional (~seq #:target-distance target-distance)) + + ;the last 2 appear to be unused in functional forge (~optional (~or (~and #:target-compare target-compare) (~and #:target-contrast target-contrast)))) ...) + (quasisyntax/loc stx (begin ;(define checker-hash (get-ast-checker-hash)) - ;(printf "sigs run ~n ch= ~a~n" checker-hash) - (define run-state curr-state) +; (printf "sigs run ~n ch= ~a~n" checker-hash) + (define run-name (~? (~@ 'name) (~@ 'no-name-provided))) (define run-preds (~? (list preds ...) (~? (list pred) (list)))) (define run-scope (~? (~@ (list (~? (~@ (list sig lower upper)) (~@ (list sig upper))) ...)) (~@ (list)))) - #;(define run-scope - (~? (list (list sig (~? lower) upper) ...) (list))) - #;(define run-scope - (~? (list (~? (list sig lower upper) (list sig upper)) ...) (list))) (define run-bounds (~? (list boundss ...) (~? (list bound) (list)))) (define run-solver (~? 'solver-choice #f)) (define run-backend (~? 'backend #f)) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; If the run has asked for an _integer expression_ to be targeted, + ; augment the run with a "gadget" which must appear in the relational bounds. + (define-values (target-pi bounds-maybe-with-gadget preds-maybe-with-gadget) + (~? + (cond + [(or (Inst? target-pi-or-int) + (hash? target-pi-or-int)) + (values target-pi-or-int run-bounds run-preds)] + [(node/int? target-pi-or-int) + ; curr-state should be a box. But that would be a wide-ranging change, + ; so instead provide a getter lambda so call-by-value works for us. + (build-int-opt-gadget target-pi-or-int run-scope run-bounds run-preds + (lambda () curr-state) + update-state! state-add-sig state-add-relation)] + [else + (raise-forge-error #:msg (format "Unexpected target type: ~a" target-pi-or-int) + #:context name)]) + (values #f run-bounds run-preds))) + (define run-target - (~? (Target target-instance ;(cdr target-instance) + (if target-pi + (Target target-pi (~? 'target-distance 'close_noretarget)) #f)) - (define run-command #'#,command) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; TODO: this _really_ ought to be a box. If the above calls update-state!, + ;; this is no longer aliased. + (define run-state curr-state) + (define run-command #'#,command) (define name (run-from-state run-state #:name run-name - #:preds run-preds + #:preds preds-maybe-with-gadget #:scope run-scope - #:bounds run-bounds + #:bounds bounds-maybe-with-gadget #:solver run-solver #:backend run-backend #:target run-target @@ -675,6 +708,7 @@ (update-state! (state-add-runmap curr-state 'name name))))])) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Primary testing form: check whether a constraint-set, under ; some provided bounds, is sat, unsat, or an error. diff --git a/forge/solver-specific/pardinus.rkt b/forge/solver-specific/pardinus.rkt index 4b9c3605..f1d059c0 100644 --- a/forge/solver-specific/pardinus.rkt +++ b/forge/solver-specific/pardinus.rkt @@ -112,13 +112,13 @@ (translate-to-kodkod-cli run-spec p all-rels all-atoms '()) (pardinus:print-cmd ")") (pardinus:assert (pardinus:f assertion-number)))) - + ; target-oriented model finding may not impose an initial target, but might ; be used just to implement custom "next" strategies (when (equal? 'target (get-option run-spec 'problem_type)) (define target (Run-spec-target run-spec)) (when target - (for ([(rel-name atoms) (Target-instance target)]) + (for ([(rel-name atoms) (Target-target target)]) (define relation (hash-ref (get-relation-map run-spec) (symbol->string rel-name))) (define sig-or-rel (if (@= (relation-arity relation) 1) @@ -169,7 +169,7 @@ (define-syntax-rule (pardinus-print lines ...) (pardinus:cmd [stdin] lines ...)) - ; If the solver isn't running at all, error: + ; If the solver process isn't running at all, error: (unless (is-running?) (raise-user-error "KodKod server is not running.")) ; If the solver is running, but this specific run ID is closed, user error diff --git a/forge/tests/forge/target/close_fixed.frg b/forge/tests/forge/target/close_fixed.frg deleted file mode 100644 index bc2c4834..00000000 --- a/forge/tests/forge/target/close_fixed.frg +++ /dev/null @@ -1,15 +0,0 @@ -#lang forge - -option run_sterling off - -option problem_type target -option solver PMaxSAT4J -option verbose 0 --- stay as close as possible to first instance -option target_mode close_noretarget -sig Node { edges: set Node } -test expect { - cover_runs: {} for 3 is sat -} - ---run {} for 3 diff --git a/forge/tests/forge/target/close_retargeting.frg b/forge/tests/forge/target/close_retargeting.frg deleted file mode 100644 index 7e172772..00000000 --- a/forge/tests/forge/target/close_retargeting.frg +++ /dev/null @@ -1,16 +0,0 @@ -#lang forge - -option run_sterling off - -option problem_type target -option solver PMaxSAT4J -option verbose 0 --- stay as close as possible to the *PRIOR* instance -option target_mode close_retarget -sig Node { edges: set Node } -test expect { - cover_runs: {} for 3 is sat -} - --- run {} for 3 - diff --git a/forge/tests/forge/target/far_fixed.frg b/forge/tests/forge/target/far_fixed.frg deleted file mode 100644 index b5699ae5..00000000 --- a/forge/tests/forge/target/far_fixed.frg +++ /dev/null @@ -1,16 +0,0 @@ -#lang forge - -option run_sterling off - -option problem_type target -option solver PMaxSAT4J -option verbose 0 --- stay as far as possible from first instance --- TODO: currently not functional without a provided target -option target_mode far_noretarget -sig Node { edges: set Node } -test expect { - cover_runs: {} for 3 is sat -} - ---run {} for 3 diff --git a/forge/tests/forge/target/far_retargeting.frg b/forge/tests/forge/target/far_retargeting.frg deleted file mode 100644 index ca12838d..00000000 --- a/forge/tests/forge/target/far_retargeting.frg +++ /dev/null @@ -1,17 +0,0 @@ -#lang forge - -option run_sterling off - -option problem_type target -option solver PMaxSAT4J -option verbose 0 --- stay as far as possible from the *PRIOR* instance --- without visiting a previously seen instance --- TODO: this is currently not working without a provided target -option target_mode far_retarget -sig Node { edges: set Node } -test expect { - cover_runs: {} for 3 is sat -} - - diff --git a/forge/tests/forge/target/hamming_runs.frg b/forge/tests/forge/target/hamming_runs.frg deleted file mode 100644 index 446f639b..00000000 --- a/forge/tests/forge/target/hamming_runs.frg +++ /dev/null @@ -1,12 +0,0 @@ -#lang forge - -option run_sterling off - -option problem_type target -option solver PMaxSAT4J -option verbose 0 -option target_mode hamming_cover -sig Node { edges: set Node } -test expect { - cover_runs: {} for 3 is sat -} diff --git a/forge/tests/forge/target/tomf.frg b/forge/tests/forge/target/tomf.frg new file mode 100644 index 00000000..4c6db4c9 --- /dev/null +++ b/forge/tests/forge/target/tomf.frg @@ -0,0 +1,151 @@ +#lang forge + +/* Testing the TOMF functionality of Forge. + Since `is sat` is too inexpressive, we define the run and then + examine the instance(s) it produces in forge/core. +*/ + +option problem_type target +option solver PMaxSAT4J + +// Not intended to run, should be called by tomf.rkt. +// If debugging, comment this line out. +option run_sterling off + +// For debugging, if needed +//option engine_verbosity 5 +//option verbose 5 + +sig Node { edges: pfunc Node -> Int } + +-- By default: stay as close as possible to first instance +-- To avoid randomly getting the empty instance (which would +-- then see a different cardinality next time), require some Node +option target_mode close_noretarget +tomf_test_defaults: run {some Node} + +tomf_test_close_noretarget_noNode: run {} + target_pi {no Node} + +// Not supported yet +//tomf_test_far_noretarget_noNode: run {} +// target_pi {no Node} far_noretarget + +// This confirms that the _partiality_ works: we don't say what +// the potential other node is connected to, if it exists. +tomf_test_close_noretarget_close_k3: run {} + target_pi { + Node = `Node0 + `Node1 + `Node2 + edges = Node -> Node -> 0 + } + +inst k3 { + Node = `Node0 + `Node1 + `Node2 + edges = Node -> Node -> 0 +} +tomf_test_use_named_inst: run {} + target_pi {k3} + +// test in presence of a constraint +tomf_test_close_k3_someIsolated: run { + some n: Node | no (n.edges) and no ~(edges.Int).n +} target_pi { + Node = `Node0 + `Node1 + `Node2 + edges = Node -> Node -> 0 +} + +// option verbose 5 + +///////////////////////////////////////////////////////////////// +// Confirm that the PI bounds are respected, though. +// N.B.: at the moment, the target must use a SUBSET of the PI bound atoms (this is a Forge-side thing) +// N.B.: also, the target needs to contain the lower-bound for the run (this is a Pardinus-side thing) +// Together, these actually restrict how we can combine PI-bounds and targets pretty significantly. +tomf_test_close_noretarget_close_k3_with_pi_bounds: run {} + // Lower/upper bounds in PI + for { + // Will be rejected by Pardinus (need verbose 5 to see the error) + // Node = `Node0 + `Node1 + `Node2 + Node in `Node0 + `Node1 + `Node2 + } + // Target lower/upper bounds + target_pi { + Node = `Node0 + `Node2 + edges = Node -> Node -> 0 + } +///////////////////////////////////////////////////////////////// + + +// Not supported yet (this example shows bad performance) +// tomf_test_far_noretarget_contains_k3: run {} +// target_pi { +// Node = `Node0 + `Node1 + `Node2 +// edges = Node -> Node -> 0 +// } far_noretarget + + +// Not supported yet (not necessarily reliable) +// tomf_test_close_retarget_noNode: run {} +// target_pi {no Node} close_retarget +// tomf_test_far_retarget_noNode: run {} +// target_pi {no Node} far_retarget +// tomf_test_hamming_noNode: run {} +// target_pi {no Node} hamming_cover + +// TODO: at present, the extra relations taint the state for all runs + +////////////////////// +// Int Minimization // +////////////////////// + +// Minimize number of nodes +tomf_test_close_noretarget_int_numNode: run {} + minimize_int {#Node} +// Make sure that the constraints are respected +tomf_test_close_noretarget_int_numNode_gte3: run {#Node >= 3} + minimize_int {#Node} + + +// This setting won't avoid, e.g., (-8 + -8 + -8) even though it "wraps" +// I believe this is because there is no _arithmetic_ involved. +option no_overflow true + +// Should give sum = -8 (mod) +tomf_test_close_noretarget_int_totalWeight4: run {} for exactly 2 Node + minimize_int {sum m: Node | sum n: Node | m.edges[n]} + +// (Not in .rkt, but here to enable performance testing.) +// Should give sum = -8 (mod) +tomf_test_close_noretarget_int_totalWeight4_6Node: run {} for 6 Node + minimize_int {sum m: Node | sum n: Node | m.edges[n]} + +// TODO: into .rkt +// What happens if we ask for all edges to have -8 weight? +// With no_overflow on, this instance is _rejected_. +tomf_test_close_noretarget_int_totalWeight4_force_many_min: run { + all n, m: Node | n.edges[m] = -8 +} for 3 Node + minimize_int {sum m: Node | sum n: Node | m.edges[n]} + + +// Should give sum = -2 (mod) +tomf_test_close_noretarget_int_totalWeight2: run {} for exactly 2 Node, 2 Int + minimize_int {sum m: Node | sum n: Node | m.edges[n]} + +// Should give sum = -16 (mod) +tomf_test_close_noretarget_int_totalWeight5: run {} for exactly 2 Node, 5 Int + minimize_int {sum m: Node | sum n: Node | m.edges[n]} + +////////////////////// +// Int Maximization // +////////////////////// + +// Maximize number of nodes +tomf_test_far_noretarget_int_numNode: run {} + maximize_int {#Node} + +// Should give sum = 8 (mod) +tomf_test_far_noretarget_int_totalWeight4: run {} for exactly 2 Node + maximize_int {sum m: Node | sum n: Node | m.edges[n]} + +/////////////////////////////////////////// diff --git a/forge/tests/forge/target/tomf.rkt b/forge/tests/forge/target/tomf.rkt new file mode 100644 index 00000000..798074e0 --- /dev/null +++ b/forge/tests/forge/target/tomf.rkt @@ -0,0 +1,261 @@ +#lang racket + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; There is a target-oriented suite under forge/core. +; This module is for the **surface syntax**. +; +; The method is adapted from error/main.rkt, but needs to be more +; complex, since this module looks at the instances produced. +; Beware: there is some technical debt here w/r/t state in Forge. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(require racket/runtime-path + (only-in rackunit check-true check-eq?) + racket/list + (for-syntax racket/base syntax/parse racket/syntax) + (only-in rackunit check-true check-eq?) + (only-in forge/sigs forge:make-model-generator forge:get-result + forge:update-state! forge:init-state + set-option! forge:Sat? Sat-instances sum-quant join) + (only-in forge/server/eval-model eval-int-expr)) + +(define (card-checker list-of-reqs) + (lambda (test-name an-instance idx) + ;(printf "~n~n~n~n~n~n~n~n~n~nChecking instance ~a: ~a~n" idx + ; (hash-remove (hash-remove (hash-remove an-instance '__K_HELPER_ATOM) '__OPT_K_HELPER) '__OPT_K_COUNT_SET)) + (for ([req list-of-reqs]) + (check-true (hash? an-instance) (format "instance for ~a is a hash?" test-name)) + (check-eq? (second req) + (length (hash-ref an-instance (first req))) + (format "size of ~a as expected for instance ~a (of ~a to be checked) of ~a" (first req) idx (length list-of-reqs) test-name))))) + +(define (same-card relname) + (define history (box #f)) + (lambda (test-name an-instance idx) + (check-true (hash? an-instance) (format "instance for ~a is a hash?" test-name)) + (if (unbox history) + (check-eq? (length (hash-ref an-instance relname)) + (unbox history) + (format "size of ~a is unchanged (=~a)for instance ~a of ~a" + relname (unbox history) idx test-name)) + (set-box! history (length (hash-ref an-instance relname)))))) + +(define-runtime-path here ".") + +; The Forge files already define the constraints to run, the scopes, etc. +; Because we actually need to look at the instances, we have to do a bit more +; work than the error testing script does. +(define-syntax (run-target-test stx) + (syntax-parse stx + [(_ #:file-name file-name #:run-name run-name (~seq #:checkers (checkers ...))) + + (with-syntax ([test-name (format-id #'stx "~a-~a" #'file-name #'run-name)] + [checkers (syntax->datum #'(list checkers ...))] + [run-name (syntax->datum #'run-name)] + [file-name (syntax->datum #'file-name)]) + #'(begin + (printf "Running for: ~a~n" 'test-name) + + (let ([root-module `(file ,(path->string (build-path here file-name)))]) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; Require the appropriate run + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ; If we set this _after_ the require, we won't see the debugging spam for setup. + ; But if we set it _before_ the require, it'll be lost when the .frg file sets it. + ; Thus, we don't set it at all in the .frg file. + (set-option! 'verbose 0) + + ; This will still only evaluate the module once, if it's already + ; been evaluated. As a result, we cannot close the solver process + ; between runs in the same file. + (define the-run (dynamic-require root-module 'run-name)) + (define sat-gen (forge:make-model-generator (forge:get-result the-run) 'next)) + + ; Walk the list of checkers, enumerating an instance for each + (for ([checker checkers] + [idx (range (length checkers))]) + (define sat-soln (sat-gen)) + (check-true (forge:Sat? sat-soln)) + (define this-instance (first (Sat-instances sat-soln))) + (checker 'test-name this-instance idx)))))])) + +;;;;;; NOTE WELL ;;;;;; +; Tests within the same module must be grouped together, for the moment. +; In fact, use only a single module. + +; Stay as close as possible to the initial instance (whatever that is) +(define same-card-defaults (same-card 'Node)) + +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_defaults + #:checkers [same-card-defaults + same-card-defaults]) + +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_noNode + #:checkers [(card-checker '((Node 0))) + (card-checker '((Node 1)))]) + +; Not yet supported +;(run-target-test #:file-name "tomf.frg" +; #:run-name tomf_test_far_noretarget_noNode +; #:checkers [(card-checker '((Node 4))) +; (card-checker '((Node 4)))]) + +; retargeting is currently buggy + +#;(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_retarget_noNode + #:checkers [(card-checker '((Node 0))) + (card-checker '((Node 1)))]) + +; Retargeting means starting as far away from empty as possible, but then +; seeking something as far away from that as possible. +#;(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_far_retarget_noNode + #:checkers [(card-checker '((Node 4))) + (card-checker '((Node 0)))]) + +; Hamming can currently cause a large slowdown in getting the 2nd model. +#;(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_hamming_noNode + #:checkers [(card-checker '((Node 0))) + (card-checker '((Node 1)))]) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Test integer-expression targeting +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; "close_noretarget" should *minimize* +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_int_numNode + #:checkers [(card-checker '((Node 0))) + (card-checker '((Node 1)))]) + +; Confirming the above in the presence of constraints that limit #Node +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_int_numNode_gte3 + #:checkers [(card-checker '((Node 3))) + (card-checker '((Node 3)))]) + + + +; "far_noretarget" should *maximize* +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_far_noretarget_int_numNode + #:checkers [(card-checker '((Node 4))) + (card-checker '((Node 4)))]) + + + +(define (sum-edges-is val min max int-size) + (lambda (test-name an-instance idx) + (check-true (hash? an-instance) (format "instance for ~a is a hash?" test-name)) + (define edges (hash-ref an-instance 'edges)) + (define sum-total (for/fold ([the-sum 0]) + ([tuple edges]) + (define so-far (+ the-sum (third tuple))) + (cond [(< so-far min) + (+ int-size so-far)] + [(> so-far max) + (- so-far int-size)] + [else so-far]))) + (check-eq? sum-total val + (format "checking for minimizing total edge weights for instance ~a of ~a" idx test-name)))) + + +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_int_totalWeight4 + #:checkers [(sum-edges-is -8 -8 7 16) + (sum-edges-is -8 -8 7 16)]) + +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_int_totalWeight2 + #:checkers [(sum-edges-is -2 -2 1 4) + (sum-edges-is -2 -2 1 4)]) + + +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_int_totalWeight5 + #:checkers [(sum-edges-is -16 -16 15 32) + (sum-edges-is -16 -16 15 32)]) + +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_far_noretarget_int_totalWeight4 + #:checkers [(sum-edges-is 7 -8 7 16) + (sum-edges-is 7 -8 7 16)]) + + + +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_close_k3 + #:checkers [(card-checker '((Node 3) + (edges 9))) + (lambda (test-name an-instance idx) + (or + ; Various ways of differing by one boolean: + ; * lose an edge + ((card-checker '((Node 3) + (edges 8))) test-name an-instance idx) + ; * add a node, same edges + ((card-checker '((Node 4) + (edges 9))) test-name an-instance idx)))]) + + +; Just confirm that named-instance version runs +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_use_named_inst + #:checkers [(card-checker '((Node 3) + (edges 9)))]) + + +; Just confirm that PI-bounds can be combined with a PI-target. +; (There are some major restrictions; see tomf.frg.) +(run-target-test #:file-name "tomf.frg" + #:run-name tomf_test_close_noretarget_close_k3_with_pi_bounds + #:checkers [(card-checker '((Node 2) + (edges 4)))]) + + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Check the tests in the change-making example +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Need to clear out the state to get rid of now-unused relations, etc. +; Forgetting to do this may cause test failures. +(forge:update-state! forge:init-state) + + +; Minimize the number of coins used +(run-target-test #:file-name "tomf_change.frg" + #:run-name change57_min_coins + #:checkers [(card-checker '((Quarter 2) (Nickel 1) (Penny 2))) + (card-checker '((Quarter 1) (Dime 2) (Nickel 2) (Penny 2))) + (card-checker '((Quarter 2) (Penny 7)))]) + +; Maximize the number of pennies and nickels used +(run-target-test #:file-name "tomf_change.frg" + #:run-name change57_max_1_5 + #:checkers [(card-checker '((Quarter 1) (Dime 1) (Nickel 3) (Penny 7)))]) + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Setup state +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Only clean up if we're about to load a new module. +;(unless (module-declared? root-module) +; Somewhat dangerous in normal circumstances, but here we have module separation +; of identifiers, but the global Forge state needs cleaning also. +;(forge:update-state! forge:init-state) +;(reset-run-name-history!) +; Don't just close-run on a run of the same name; restart the entire solver engine. +;(stop-solver-process!) +; ) + diff --git a/forge/tests/forge/target/tomf_change.frg b/forge/tests/forge/target/tomf_change.frg new file mode 100644 index 00000000..61cd84f6 --- /dev/null +++ b/forge/tests/forge/target/tomf_change.frg @@ -0,0 +1,74 @@ +#lang forge + +/* + Let's test integer minimization in a different sort of problem, + making change. This will involve a larger bitwidth and has a + different sort of feel to it. + + We won't try to optimize the numeric reasoning here: the value + of coins is set with constraints, not a partial-inst optimizer. +*/ + +option problem_type target +option solver PMaxSAT4J + +abstract sig Coin {} +sig Penny, Nickel, Dime, Quarter extends Coin {} + +one sig Transaction { + change: one Int +} + +fun valueOf[c: Coin]: one Int { + c in Penny => 1 else + c in Nickel => 5 else + c in Dime => 10 else 25 +} + +pred correctChangeMade { + // We assume the set of Coin atoms corresponds to the available + // drawer of change. So we just check the total: + (sum c: Coin | valueOf[c]) = Transaction.change +} +pred correct57 { + // Return $0.57 in change + Transaction.change = 57 + // and do so correctly + correctChangeMade + + // with a specific drawer state + #Quarter <= 2 + #Dime <= 2 + #Nickel <= 3 + #Penny <= 8 + + // Note: the test runner (tomf.rkt) that uses this module will examine + // the cardinality of these sigs in a given instance to decide if the + // instance is expected. Hence why these are given as _upper_ bounds. + // I.e., all Coin atoms are part of the change given. + +} + +//////////////////////////////////////////////////////////////////////////// + +// Minimize the number of coins used. This will produce +// Instance 1: 5 coins (2 quarters, 1 nickel, 2 pennies) +// Instance 2: 7 coins (1 quarter, 2 dimes, 2 nickels, 2 pennies) +// (There is no way to solve this with exactly 6 coins, given the drawer. +// We need 2 pennies at minimum, leaving us only 4 to make 55 cents.) +// Instance 3: 9 coins (2 quarters, 7 pennies) +change57_min_coins: run {correct57} for 8 Int, 15 Coin + minimize_int {#Coin} + +//////////////////////////////////////////////////////////////////////////// + +// Maximize the number of pennies used (someone paid with multiple +// rolls earlier for some reason) +// Instance 1: (1 quarter, 1 dime, 3 nickels, 7 pennies) + +change57_max_1_5: run {correct57} for 8 Int, 15 Coin + maximize_int {#(Penny + Nickel)} + +//////////////////////////////////////////////////////////////////////////// + +// ? Can we express "it is impossible to...?" This seems like H.O. universal. diff --git a/forge/utils/collector.rkt b/forge/utils/collector.rkt index ac321cb9..bc02eab5 100644 --- a/forge/utils/collector.rkt +++ b/forge/utils/collector.rkt @@ -90,7 +90,7 @@ ; Translate a formula AST node (define (interpret-formula formula quantvars matcher order collected stop context get-new-context) - (when (@>= (get-verbosity) VERBOSITY_HIGH) + (when (@>= (get-verbosity) VERBOSITY_DEBUG) (printf "collector: interpret-formula: ~a~n" formula)) (match formula [(node/formula/constant info type) @@ -112,7 +112,7 @@ (define (process-children children quantvars) (apply append (map (lambda (x) (visit x quantvars matcher order collected stop context get-new-context)) children))) - (when (@>= (get-verbosity) VERBOSITY_HIGH) + (when (@>= (get-verbosity) VERBOSITY_DEBUG) (printf "collector: interpret-formula-op: ~a~n" formula)) ; We could get away with only one case here, really, since there's no distinguishing ; but leaving the structure here for now in case we need it for any refinement. @@ -161,7 +161,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (interpret-expr expr quantvars matcher order collected stop context get-new-context) - (when (@>= (get-verbosity) VERBOSITY_HIGH) + (when (@>= (get-verbosity) VERBOSITY_DEBUG) (printf "collector: interpret-expr: ~a~n" expr)) (match expr [(node/expr/relation info arity name typelist-thunk parent isvar) @@ -190,7 +190,7 @@ (define (process-children children quantvars) (apply append (map (lambda (x) (visit x quantvars matcher order collected stop context get-new-context)) children))) - (when (@>= (get-verbosity) VERBOSITY_HIGH) + (when (@>= (get-verbosity) VERBOSITY_DEBUG) (printf "collector: interpret-expr-op: ~a~n" expr)) ; We could get away with only one case here, really, since there's no distinguishing ; but leaving the structure here for now in case we need it for any refinement. @@ -223,7 +223,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (define (interpret-int expr quantvars matcher order collected stop context get-new-context) - (when (@>= (get-verbosity) VERBOSITY_HIGH) + (when (@>= (get-verbosity) VERBOSITY_DEBUG) (printf "collector: interpret-int: ~a~n" expr)) (match expr [(node/int/constant info value) @@ -252,7 +252,7 @@ (define (process-children children quantvars) (apply append (map (lambda (x) (visit x quantvars matcher order collected stop context get-new-context)) children))) - (when (@>= (get-verbosity) VERBOSITY_HIGH) + (when (@>= (get-verbosity) VERBOSITY_DEBUG) (printf "collector: interpret-int-op: ~a~n" expr)) ; We could get away with only one case here, really, since there's no distinguishing diff --git a/forge/utils/target-oriented.rkt b/forge/utils/target-oriented.rkt new file mode 100644 index 00000000..f15d71bb --- /dev/null +++ b/forge/utils/target-oriented.rkt @@ -0,0 +1,183 @@ +#lang racket/base + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Helper module for gadgets related to target-oriented model finding +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(require (prefix-in @ (only-in racket/base - +)) + forge/sigs-functional + (only-in forge/lang/ast atom -> + int) + racket/list) + +(provide build-int-opt-gadget) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Integer minimization/optimization +; +; Encode an integer-expression minimization problem as a relation +; minimization problem for Pardinus' target-oriented solver. The strategy +; works with the help of 3 hidden relations: +; +; (1) A sig `__K_HELPER_ATOM`, which contains exactly 2^{bitwidth} distinct +; new atoms. +; (2) A 2-ary relation `__OPT_K_HELPER` on (Int -> _K_HELPER_ATOM), mapping +; integer values within the current bitwidth to sets of helper atoms. +; Each integer maps to a different set that contains the prior int's set +; (if any). The distinct min[Int] maps to the empty set. +; (3) A sig `__OPT_K_COUNT_SET`, extending `__K_HELPER_ATOM`. +; +; We then add two new components to the solver problem: +; +; (A) A partial instance `__OPT_K_INST` that exact bounds `__K_HELPER_ATOM` +; and `__OPT_K_COUNT_SET` according to the current bitwidth. We could +; use constraints here, but using a partial instance will be more efficient. +; (B) A constraint that the contents of `__OPT_K_COUNT_SET` are equal to the join: +; ( . __OPT_K_HELPER) +; where is the minimization target. +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define (list-helper-atoms kmin kmax) + ; E.g., from -8 to +7: `__HELPER0 through `__HELPER15 + (build-list (@+ 1 (@- kmax kmin)) + (lambda (v) + (atom (string->symbol (format "__HELPER~a" v)))))) + +(define (list-helper-tuples kmin kmax) + ; E.g., from -8 to +7: (-7 -> `__HELPER0) + (-6 -> (`__HELPER0 + `__HELPER1)) + ... + ; min[Int] is represented by the empty set: "no (min[Int]).__OPT_K_HELPER)" holds. + (build-list (@- kmax kmin) + (lambda (offset) + (-> (int (@+ kmin offset 1)) + (if (eq? offset 0) + (atom (string->symbol "__HELPER0")) + (+ (build-list (@+ offset 1) + (lambda (atomnum) + (atom (string->symbol (format "__HELPER~a" atomnum))))))))))) + + +; Given an integer expression, generate a "gadget" in the form +; of additional partial bounds and additional constraints that +; will aid in translating the integer expression target to a +; standard relational target. +(define (build-int-opt-gadget given-int-expr run-scope run-bounds run-preds + get-curr-state update-state! state-add-sig state-add-relation) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; Step 1: set up the fixed helper relations and prepare to build bounds. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + ; Because the notion of the "state" is so entangled with the run pipeline, we'll + ; enable these helper relations permanently as soon as Forge processes _one_ of + ; these integer-optimization commands. This isn't ideal. + + ; The full set of possible helper atoms + (define __K_HELPER_ATOM + (cond [(get-sig (get-curr-state) '__K_HELPER_ATOM) + (get-sig (get-curr-state) '__K_HELPER_ATOM)] + [else + (let ([new-sig (make-sig '__K_HELPER_ATOM)]) + (update-state! (state-add-sig (get-curr-state) + '__K_HELPER_ATOM + new-sig #f)) + new-sig)])) + + ; The exact-bounded helper relation + (define __OPT_K_HELPER + (cond [(get-relation (get-curr-state) '__OPT_K_HELPER) + (get-relation (get-curr-state) '__OPT_K_HELPER)] + [else + (let ([new-rel (make-relation '__OPT_K_HELPER (list Int __K_HELPER_ATOM))]) + (update-state! (state-add-relation (get-curr-state) '__OPT_K_HELPER new-rel)) + new-rel)])) + + ; The set of counting-helper atoms that are used in a given instance + (define __OPT_K_COUNT_SET + (cond [(get-sig (get-curr-state) '__OPT_K_COUNT_SET) + (get-sig (get-curr-state) '__OPT_K_COUNT_SET)] + [else + (let ([new-sig (make-sig '__OPT_K_COUNT_SET #:extends __K_HELPER_ATOM)]) + (update-state! (state-add-sig (get-curr-state) + '__OPT_K_COUNT_SET + new-sig #f)) + new-sig)])) + + (define (bind-k-helper-atom kmin kmax) + (= __K_HELPER_ATOM (+ (list-helper-atoms kmin kmax)))) + + (define (bind-opt-k-helper kmin kmax) + (= __OPT_K_HELPER (+ (list-helper-tuples kmin kmax)))) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; Step 2: Use the bitwidth given by the actual Forge problem to + ; generate bounds on the helper relations. We get this from the scope, + ; but this might be either a Scope struct or a list of size lists. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (define-values (bitwidth found?) + (cond [(Scope? run-scope) (Scope-bitwidth run-scope)] + [(list? run-scope) + (for/fold ([bw DEFAULT-BITWIDTH] + [found? #f]) + ([sc run-scope]) + (cond [(and (equal? Int (first sc)) + (equal? (length sc) 2)) + (values (second sc) #t)] + [(and (equal? Int (first sc)) + (equal? (length sc) 3)) + (values (third sc) #t)] + [(equal? Int (first sc)) + (raise-forge-error #:msg (format "Unexpected scope-list format: ~a~n" sc) + #:context #f)] + [else (if found? + (values bw #t) + (values DEFAULT-BITWIDTH #f))]))] + [else + (raise-forge-error #:msg (format "Unexpected scope format: ~a~n") + #:context #f)])) + + (define num-ints (expt 2 bitwidth)) + (define min-int (@- (/ num-ints 2))) + (define max-int (@- (/ num-ints 2) 1)) + + (define __OPT_K_INST + (make-inst + (list (bind-k-helper-atom min-int max-int) + (bind-opt-k-helper min-int max-int)))) + + ; ...will be the result of looking up the given-int-expr's value in the __OPT_K_HELPER table. + (define __OPT_K_WELLFORMED (= __OPT_K_COUNT_SET (join given-int-expr __OPT_K_HELPER))) + + (values + ; the target, in hash-instance format + (hash '__OPT_K_COUNT_SET '()) + ; the augmented relational bounds + (or (and (Inst? run-bounds) (make-inst (list __OPT_K_INST run-bounds))) + __OPT_K_INST) + ; the augmented constraint set + (cons __OPT_K_WELLFORMED run-preds) + ; the two sigs + ;(list __OPT_K_COUNT_SET __K_HELPER_ATOM) + ; the one relation + ;(list __OPT_K_HELPER) + )) + + + + + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Step 3: Create the run +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; Note well: this excludes temporal mode +;(set-option! 'problem_type 'target) +; Note well: this isn't supported on all operating systems yet +;(set-option! 'solver 'PMaxSAT4J) + +; Overflows can make this look strange. E.g., at bitwidth 3, 8 edges, becomes "minimal" for #edges. +;(set-option! 'no_overflow 'true) +; We also need to make sure that the given bitwidth above actually matches the bitwidth of the run. + + From 3a304e9ba2d7dc6f9bf71e45ba62596ecaaca68d Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Wed, 28 May 2025 10:55:17 -0400 Subject: [PATCH 06/22] Avoid identifier clash between expander macros and user-defined sigs, etc. (#307) See PR #307 --- {forge => OLD}/check-ex-spec/README.md | 0 .../check-ex-spec/core/lang/reader.rkt | 0 {forge => OLD}/check-ex-spec/core/main.rkt | 0 .../check-ex-spec/demo/demo-suite.rkt | 0 .../sample-student/student-sample-core.rkt | 0 .../sample-student/student-sample-surface.rkt | 0 .../sample-ta/sample/chaffs/sample-chaff1.rkt | 0 .../sample-ta/sample/chaffs/sample-chaff2.rkt | 0 .../sample-ta/sample/wheats/sample-wheat.rkt | 0 .../check-ex-spec/examples/ta-template/README | 0 .../examples/ta-template/config.sh | 0 .../check-ex-spec/examples/ta-template/new.sh | 0 .../examples/ta-template/publish.sh | 0 .../examples/ta-template/setup.sh | 0 .../examples/ta-template/summarize.rkt | 0 {forge => OLD}/check-ex-spec/info.rkt | 0 .../check-ex-spec/lang/expander.rkt | 0 {forge => OLD}/check-ex-spec/lang/reader.rkt | 0 {forge => OLD}/check-ex-spec/library.rkt | 0 .../check-ex-spec/library/commands.rkt | 0 .../check-ex-spec/library/download-file.rkt | 0 {forge => OLD}/check-ex-spec/main.rkt | 0 {forge => OLD}/testme/core/lang/reader.rkt | 0 {forge => OLD}/testme/core/main.rkt | 0 .../sample-student/student-sample-core.rkt | 0 .../sample-student/student-sample-surface.rkt | 0 .../sample-ta/sample/chaffs/sample-chaff1.rkt | 0 .../sample-ta/sample/chaffs/sample-chaff2.rkt | 0 .../sample-ta/sample/wheats/sample-wheat.rkt | 0 .../testme/examples/ta-template/README | 0 .../testme/examples/ta-template/config.sh | 0 .../testme/examples/ta-template/new.sh | 0 .../testme/examples/ta-template/publish.sh | 0 .../testme/examples/ta-template/setup.sh | 0 .../testme/examples/ta-template/summarize.rkt | 0 {forge => OLD}/testme/info.rkt | 0 {forge => OLD}/testme/lang/expander.rkt | 0 {forge => OLD}/testme/lang/reader.rkt | 0 {forge => OLD}/testme/library.rkt | 0 {forge => OLD}/testme/library/commands.rkt | 0 .../testme/library/download-file.rkt | 0 {forge => OLD}/testme/main.rkt | 0 forge/lang/alloy-syntax/parser.rkt | 177 ++++----- forge/lang/expander.rkt | 349 +++++++++--------- forge/lang/reader.rkt | 10 +- forge/server/forgeserver.rkt | 4 +- .../translate-to-kodkod-cli.rkt | 4 +- forge/tests/forge/other/empty.frg | 3 + .../tests/forge/other/internal-ids-preds.frg | 128 +++++++ forge/tests/forge/other/internal-ids-sigs.frg | 86 +++++ 50 files changed, 498 insertions(+), 263 deletions(-) rename {forge => OLD}/check-ex-spec/README.md (100%) rename {forge => OLD}/check-ex-spec/core/lang/reader.rkt (100%) rename {forge => OLD}/check-ex-spec/core/main.rkt (100%) rename {forge => OLD}/check-ex-spec/demo/demo-suite.rkt (100%) rename {forge => OLD}/check-ex-spec/examples/sample-student/student-sample-core.rkt (100%) rename {forge => OLD}/check-ex-spec/examples/sample-student/student-sample-surface.rkt (100%) rename {forge => OLD}/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff1.rkt (100%) rename {forge => OLD}/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff2.rkt (100%) rename {forge => OLD}/check-ex-spec/examples/sample-ta/sample/wheats/sample-wheat.rkt (100%) rename {forge => OLD}/check-ex-spec/examples/ta-template/README (100%) rename {forge => OLD}/check-ex-spec/examples/ta-template/config.sh (100%) rename {forge => OLD}/check-ex-spec/examples/ta-template/new.sh (100%) rename {forge => OLD}/check-ex-spec/examples/ta-template/publish.sh (100%) rename {forge => OLD}/check-ex-spec/examples/ta-template/setup.sh (100%) rename {forge => OLD}/check-ex-spec/examples/ta-template/summarize.rkt (100%) rename {forge => OLD}/check-ex-spec/info.rkt (100%) rename {forge => OLD}/check-ex-spec/lang/expander.rkt (100%) rename {forge => OLD}/check-ex-spec/lang/reader.rkt (100%) rename {forge => OLD}/check-ex-spec/library.rkt (100%) rename {forge => OLD}/check-ex-spec/library/commands.rkt (100%) rename {forge => OLD}/check-ex-spec/library/download-file.rkt (100%) rename {forge => OLD}/check-ex-spec/main.rkt (100%) rename {forge => OLD}/testme/core/lang/reader.rkt (100%) rename {forge => OLD}/testme/core/main.rkt (100%) rename {forge => OLD}/testme/examples/sample-student/student-sample-core.rkt (100%) rename {forge => OLD}/testme/examples/sample-student/student-sample-surface.rkt (100%) rename {forge => OLD}/testme/examples/sample-ta/sample/chaffs/sample-chaff1.rkt (100%) rename {forge => OLD}/testme/examples/sample-ta/sample/chaffs/sample-chaff2.rkt (100%) rename {forge => OLD}/testme/examples/sample-ta/sample/wheats/sample-wheat.rkt (100%) rename {forge => OLD}/testme/examples/ta-template/README (100%) rename {forge => OLD}/testme/examples/ta-template/config.sh (100%) rename {forge => OLD}/testme/examples/ta-template/new.sh (100%) rename {forge => OLD}/testme/examples/ta-template/publish.sh (100%) rename {forge => OLD}/testme/examples/ta-template/setup.sh (100%) rename {forge => OLD}/testme/examples/ta-template/summarize.rkt (100%) rename {forge => OLD}/testme/info.rkt (100%) rename {forge => OLD}/testme/lang/expander.rkt (100%) rename {forge => OLD}/testme/lang/reader.rkt (100%) rename {forge => OLD}/testme/library.rkt (100%) rename {forge => OLD}/testme/library/commands.rkt (100%) rename {forge => OLD}/testme/library/download-file.rkt (100%) rename {forge => OLD}/testme/main.rkt (100%) create mode 100644 forge/tests/forge/other/empty.frg create mode 100644 forge/tests/forge/other/internal-ids-preds.frg create mode 100644 forge/tests/forge/other/internal-ids-sigs.frg diff --git a/forge/check-ex-spec/README.md b/OLD/check-ex-spec/README.md similarity index 100% rename from forge/check-ex-spec/README.md rename to OLD/check-ex-spec/README.md diff --git a/forge/check-ex-spec/core/lang/reader.rkt b/OLD/check-ex-spec/core/lang/reader.rkt similarity index 100% rename from forge/check-ex-spec/core/lang/reader.rkt rename to OLD/check-ex-spec/core/lang/reader.rkt diff --git a/forge/check-ex-spec/core/main.rkt b/OLD/check-ex-spec/core/main.rkt similarity index 100% rename from forge/check-ex-spec/core/main.rkt rename to OLD/check-ex-spec/core/main.rkt diff --git a/forge/check-ex-spec/demo/demo-suite.rkt b/OLD/check-ex-spec/demo/demo-suite.rkt similarity index 100% rename from forge/check-ex-spec/demo/demo-suite.rkt rename to OLD/check-ex-spec/demo/demo-suite.rkt diff --git a/forge/check-ex-spec/examples/sample-student/student-sample-core.rkt b/OLD/check-ex-spec/examples/sample-student/student-sample-core.rkt similarity index 100% rename from forge/check-ex-spec/examples/sample-student/student-sample-core.rkt rename to OLD/check-ex-spec/examples/sample-student/student-sample-core.rkt diff --git a/forge/check-ex-spec/examples/sample-student/student-sample-surface.rkt b/OLD/check-ex-spec/examples/sample-student/student-sample-surface.rkt similarity index 100% rename from forge/check-ex-spec/examples/sample-student/student-sample-surface.rkt rename to OLD/check-ex-spec/examples/sample-student/student-sample-surface.rkt diff --git a/forge/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff1.rkt b/OLD/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff1.rkt similarity index 100% rename from forge/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff1.rkt rename to OLD/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff1.rkt diff --git a/forge/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff2.rkt b/OLD/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff2.rkt similarity index 100% rename from forge/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff2.rkt rename to OLD/check-ex-spec/examples/sample-ta/sample/chaffs/sample-chaff2.rkt diff --git a/forge/check-ex-spec/examples/sample-ta/sample/wheats/sample-wheat.rkt b/OLD/check-ex-spec/examples/sample-ta/sample/wheats/sample-wheat.rkt similarity index 100% rename from forge/check-ex-spec/examples/sample-ta/sample/wheats/sample-wheat.rkt rename to OLD/check-ex-spec/examples/sample-ta/sample/wheats/sample-wheat.rkt diff --git a/forge/check-ex-spec/examples/ta-template/README b/OLD/check-ex-spec/examples/ta-template/README similarity index 100% rename from forge/check-ex-spec/examples/ta-template/README rename to OLD/check-ex-spec/examples/ta-template/README diff --git a/forge/check-ex-spec/examples/ta-template/config.sh b/OLD/check-ex-spec/examples/ta-template/config.sh similarity index 100% rename from forge/check-ex-spec/examples/ta-template/config.sh rename to OLD/check-ex-spec/examples/ta-template/config.sh diff --git a/forge/check-ex-spec/examples/ta-template/new.sh b/OLD/check-ex-spec/examples/ta-template/new.sh similarity index 100% rename from forge/check-ex-spec/examples/ta-template/new.sh rename to OLD/check-ex-spec/examples/ta-template/new.sh diff --git a/forge/check-ex-spec/examples/ta-template/publish.sh b/OLD/check-ex-spec/examples/ta-template/publish.sh similarity index 100% rename from forge/check-ex-spec/examples/ta-template/publish.sh rename to OLD/check-ex-spec/examples/ta-template/publish.sh diff --git a/forge/check-ex-spec/examples/ta-template/setup.sh b/OLD/check-ex-spec/examples/ta-template/setup.sh similarity index 100% rename from forge/check-ex-spec/examples/ta-template/setup.sh rename to OLD/check-ex-spec/examples/ta-template/setup.sh diff --git a/forge/check-ex-spec/examples/ta-template/summarize.rkt b/OLD/check-ex-spec/examples/ta-template/summarize.rkt similarity index 100% rename from forge/check-ex-spec/examples/ta-template/summarize.rkt rename to OLD/check-ex-spec/examples/ta-template/summarize.rkt diff --git a/forge/check-ex-spec/info.rkt b/OLD/check-ex-spec/info.rkt similarity index 100% rename from forge/check-ex-spec/info.rkt rename to OLD/check-ex-spec/info.rkt diff --git a/forge/check-ex-spec/lang/expander.rkt b/OLD/check-ex-spec/lang/expander.rkt similarity index 100% rename from forge/check-ex-spec/lang/expander.rkt rename to OLD/check-ex-spec/lang/expander.rkt diff --git a/forge/check-ex-spec/lang/reader.rkt b/OLD/check-ex-spec/lang/reader.rkt similarity index 100% rename from forge/check-ex-spec/lang/reader.rkt rename to OLD/check-ex-spec/lang/reader.rkt diff --git a/forge/check-ex-spec/library.rkt b/OLD/check-ex-spec/library.rkt similarity index 100% rename from forge/check-ex-spec/library.rkt rename to OLD/check-ex-spec/library.rkt diff --git a/forge/check-ex-spec/library/commands.rkt b/OLD/check-ex-spec/library/commands.rkt similarity index 100% rename from forge/check-ex-spec/library/commands.rkt rename to OLD/check-ex-spec/library/commands.rkt diff --git a/forge/check-ex-spec/library/download-file.rkt b/OLD/check-ex-spec/library/download-file.rkt similarity index 100% rename from forge/check-ex-spec/library/download-file.rkt rename to OLD/check-ex-spec/library/download-file.rkt diff --git a/forge/check-ex-spec/main.rkt b/OLD/check-ex-spec/main.rkt similarity index 100% rename from forge/check-ex-spec/main.rkt rename to OLD/check-ex-spec/main.rkt diff --git a/forge/testme/core/lang/reader.rkt b/OLD/testme/core/lang/reader.rkt similarity index 100% rename from forge/testme/core/lang/reader.rkt rename to OLD/testme/core/lang/reader.rkt diff --git a/forge/testme/core/main.rkt b/OLD/testme/core/main.rkt similarity index 100% rename from forge/testme/core/main.rkt rename to OLD/testme/core/main.rkt diff --git a/forge/testme/examples/sample-student/student-sample-core.rkt b/OLD/testme/examples/sample-student/student-sample-core.rkt similarity index 100% rename from forge/testme/examples/sample-student/student-sample-core.rkt rename to OLD/testme/examples/sample-student/student-sample-core.rkt diff --git a/forge/testme/examples/sample-student/student-sample-surface.rkt b/OLD/testme/examples/sample-student/student-sample-surface.rkt similarity index 100% rename from forge/testme/examples/sample-student/student-sample-surface.rkt rename to OLD/testme/examples/sample-student/student-sample-surface.rkt diff --git a/forge/testme/examples/sample-ta/sample/chaffs/sample-chaff1.rkt b/OLD/testme/examples/sample-ta/sample/chaffs/sample-chaff1.rkt similarity index 100% rename from forge/testme/examples/sample-ta/sample/chaffs/sample-chaff1.rkt rename to OLD/testme/examples/sample-ta/sample/chaffs/sample-chaff1.rkt diff --git a/forge/testme/examples/sample-ta/sample/chaffs/sample-chaff2.rkt b/OLD/testme/examples/sample-ta/sample/chaffs/sample-chaff2.rkt similarity index 100% rename from forge/testme/examples/sample-ta/sample/chaffs/sample-chaff2.rkt rename to OLD/testme/examples/sample-ta/sample/chaffs/sample-chaff2.rkt diff --git a/forge/testme/examples/sample-ta/sample/wheats/sample-wheat.rkt b/OLD/testme/examples/sample-ta/sample/wheats/sample-wheat.rkt similarity index 100% rename from forge/testme/examples/sample-ta/sample/wheats/sample-wheat.rkt rename to OLD/testme/examples/sample-ta/sample/wheats/sample-wheat.rkt diff --git a/forge/testme/examples/ta-template/README b/OLD/testme/examples/ta-template/README similarity index 100% rename from forge/testme/examples/ta-template/README rename to OLD/testme/examples/ta-template/README diff --git a/forge/testme/examples/ta-template/config.sh b/OLD/testme/examples/ta-template/config.sh similarity index 100% rename from forge/testme/examples/ta-template/config.sh rename to OLD/testme/examples/ta-template/config.sh diff --git a/forge/testme/examples/ta-template/new.sh b/OLD/testme/examples/ta-template/new.sh similarity index 100% rename from forge/testme/examples/ta-template/new.sh rename to OLD/testme/examples/ta-template/new.sh diff --git a/forge/testme/examples/ta-template/publish.sh b/OLD/testme/examples/ta-template/publish.sh similarity index 100% rename from forge/testme/examples/ta-template/publish.sh rename to OLD/testme/examples/ta-template/publish.sh diff --git a/forge/testme/examples/ta-template/setup.sh b/OLD/testme/examples/ta-template/setup.sh similarity index 100% rename from forge/testme/examples/ta-template/setup.sh rename to OLD/testme/examples/ta-template/setup.sh diff --git a/forge/testme/examples/ta-template/summarize.rkt b/OLD/testme/examples/ta-template/summarize.rkt similarity index 100% rename from forge/testme/examples/ta-template/summarize.rkt rename to OLD/testme/examples/ta-template/summarize.rkt diff --git a/forge/testme/info.rkt b/OLD/testme/info.rkt similarity index 100% rename from forge/testme/info.rkt rename to OLD/testme/info.rkt diff --git a/forge/testme/lang/expander.rkt b/OLD/testme/lang/expander.rkt similarity index 100% rename from forge/testme/lang/expander.rkt rename to OLD/testme/lang/expander.rkt diff --git a/forge/testme/lang/reader.rkt b/OLD/testme/lang/reader.rkt similarity index 100% rename from forge/testme/lang/reader.rkt rename to OLD/testme/lang/reader.rkt diff --git a/forge/testme/library.rkt b/OLD/testme/library.rkt similarity index 100% rename from forge/testme/library.rkt rename to OLD/testme/library.rkt diff --git a/forge/testme/library/commands.rkt b/OLD/testme/library/commands.rkt similarity index 100% rename from forge/testme/library/commands.rkt rename to OLD/testme/library/commands.rkt diff --git a/forge/testme/library/download-file.rkt b/OLD/testme/library/download-file.rkt similarity index 100% rename from forge/testme/library/download-file.rkt rename to OLD/testme/library/download-file.rkt diff --git a/forge/testme/main.rkt b/OLD/testme/main.rkt similarity index 100% rename from forge/testme/main.rkt rename to OLD/testme/main.rkt diff --git a/forge/lang/alloy-syntax/parser.rkt b/forge/lang/alloy-syntax/parser.rkt index 978c3415..d03ea4b3 100644 --- a/forge/lang/alloy-syntax/parser.rkt +++ b/forge/lang/alloy-syntax/parser.rkt @@ -26,37 +26,37 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Starting production for the parser ; Two options: a model, or an evaluation request -AlloyModule : - Import* Paragraph* - | EvalDecl* +NT-AlloyModule : + NT-Import* Paragraph* + | NT-EvalDecl* ; Import other Forge files by name -Import : /OPEN-TOK QualName (LEFT-SQUARE-TOK QualNameList RIGHT-SQUARE-TOK)? (AS-TOK Name)? +NT-Import : /OPEN-TOK QualName (LEFT-SQUARE-TOK QualNameList RIGHT-SQUARE-TOK)? (AS-TOK Name)? | /OPEN-TOK PATH-OR-STR-TOK (AS-TOK Name)? ; Basic top-level constructs of a model: sigs, preds, commands, etc. @Paragraph : - SigDecl - | PredDecl - | FunDecl - | AssertDecl - | CmdDecl - | TestExpectDecl - | SexprDecl - | QueryDecl - | EvalRelDecl - | OptionDecl - | InstDecl - | ExampleDecl - | PropertyDecl - | QuantifiedPropertyDecl - | SatisfiabilityDecl - | ConsistencyDecl - | TestSuiteDecl + NT-SigDecl + | NT-PredDecl + | NT-FunDecl + | NT-AssertDecl + | NT-CmdDecl + | NT-TestExpectDecl + | NT-SexprDecl + | NT-QueryDecl + | NT-EvalRelDecl + | NT-OptionDecl + | NT-InstDecl + | NT-ExampleDecl + | NT-PropertyDecl + | NT-QuantifiedPropertyDecl + | NT-SatisfiabilityDecl + | NT-ConsistencyDecl + | NT-TestSuiteDecl ; NOTE: When extending sigs with "in" (subset sigs) is implemented, ; if "sig A in B extends C" is allowed, update this to allow multiple SigExt -SigDecl : VAR-TOK? ABSTRACT-TOK? Mult? /SIG-TOK NameList SigExt? /LEFT-CURLY-TOK ArrowDeclList? /RIGHT-CURLY-TOK Block? +NT-SigDecl : VAR-TOK? ABSTRACT-TOK? Mult? /SIG-TOK NameList SigExt? /LEFT-CURLY-TOK ArrowDeclList? /RIGHT-CURLY-TOK NT-Block? SigExt : EXTENDS-TOK QualName | IN-TOK QualName (PLUS-TOK QualName)* @@ -65,8 +65,8 @@ Mult : LONE-TOK | SOME-TOK | ONE-TOK | TWO-TOK ArrowMult : LONE-TOK | SET-TOK | ONE-TOK | TWO-TOK | FUNC-TOK | PFUNC-TOK ; for helper fun/pred declaration HelperMult : LONE-TOK | SET-TOK | ONE-TOK | FUNC-TOK | PFUNC-TOK -ParaDecl : DISJ-TOK? NameList /COLON-TOK HelperMult? Expr -QuantDecl : DISJ-TOK? NameList /COLON-TOK SET-TOK? Expr +ParaDecl : DISJ-TOK? NameList /COLON-TOK HelperMult? NT-Expr +QuantDecl : DISJ-TOK? NameList /COLON-TOK SET-TOK? NT-Expr ; ArrowDecl should only be used by sig field declaration right now; ; note the optional VAR for Electrum. Remember that a preceding / means @@ -76,9 +76,9 @@ ArrowDecl : VAR-TOK? NameList /COLON-TOK ArrowMult ArrowExpr PredType : WHEAT-TOK ; A predicate declaration can contain any number of formulas in its body -PredDecl : /PRED-TOK PredType? (QualName DOT-TOK)? Name ParaDecls? Block +NT-PredDecl : /PRED-TOK PredType? (QualName DOT-TOK)? Name ParaDecls? NT-Block ; A function declaration should only ever contain a single expression in its body -FunDecl : /FUN-TOK (QualName DOT-TOK)? Name ParaDecls? /COLON-TOK HelperMult? Expr /LEFT-CURLY-TOK Expr /RIGHT-CURLY-TOK +NT-FunDecl : /FUN-TOK (QualName DOT-TOK)? Name ParaDecls? /COLON-TOK HelperMult? NT-Expr /LEFT-CURLY-TOK NT-Expr /RIGHT-CURLY-TOK ; A ParaDecls is a special declaration form for pred/fun definition, where every identifier ; is paired with an expr and (optional) multiplicity ParaDecls : /LEFT-PAREN-TOK @ParaDeclList? /RIGHT-PAREN-TOK @@ -87,39 +87,40 @@ ParaDecls : /LEFT-PAREN-TOK @ParaDeclList? /RIGHT-PAREN-TOK ; Configure target-oriented model finding, or integer optimization (which builds on TOMF). ; Expect the type of targeted search, followed by the target, and then the mode (optionally). TOMFParams : TARGET_PI-TOK Bounds - | MINIMIZE_INT-TOK Block - | MAXIMIZE_INT-TOK Block + | MINIMIZE_INT-TOK NT-Block + | MAXIMIZE_INT-TOK NT-Block -AssertDecl : /ASSERT-TOK Name? Block -CmdDecl : Name /COLON-TOK (RUN-TOK | CHECK-TOK) (QualName | Block)? Scope? (/FOR-TOK Bounds)? (TOMFParams)? - | (RUN-TOK | CHECK-TOK) (QualName | Block)? Scope? (/FOR-TOK Bounds)? (TOMFParams)? +NT-AssertDecl : /ASSERT-TOK Name? NT-Block +NT-CmdDecl : Name /COLON-TOK (RUN-TOK | CHECK-TOK) (QualName | NT-Block)? Scope? (/FOR-TOK Bounds)? (TOMFParams)? + | (RUN-TOK | CHECK-TOK) (QualName | NT-Block)? Scope? (/FOR-TOK Bounds)? (TOMFParams)? -TestDecl : (Name /COLON-TOK)? (QualName | Block) Scope? (/FOR-TOK Bounds)? /IS-TOK +NT-TestDecl : (Name /COLON-TOK)? (QualName | NT-Block) Scope? (/FOR-TOK Bounds)? /IS-TOK (SAT-TOK | UNSAT-TOK | UNKNOWN-TOK | THEOREM-TOK | FORGE_ERROR-TOK (PATH-OR-STR-TOK)? | CHECKED-TOK ) -TestExpectDecl : TEST-TOK? EXPECT-TOK Name? TestBlock -TestBlock : /LEFT-CURLY-TOK TestDecl* /RIGHT-CURLY-TOK +NT-TestExpectDecl : TEST-TOK? EXPECT-TOK Name? TestBlock +TestBlock : /LEFT-CURLY-TOK NT-TestDecl* /RIGHT-CURLY-TOK Scope : /FOR-TOK Number (/BUT-TOK @TypescopeList)? | /FOR-TOK @TypescopeList Typescope : EXACTLY-TOK? Number QualName Const : NONE-TOK | UNIV-TOK | IDEN-TOK | MINUS-TOK? Number -SatisfiabilityDecl : Name /COLON-TOK /ASSERT-TOK Expr /IS-TOK (SAT-TOK | UNSAT-TOK | FORGE_ERROR-TOK) Scope? (/FOR-TOK Bounds)? - | /ASSERT-TOK Expr /IS-TOK (SAT-TOK | UNSAT-TOK | FORGE_ERROR-TOK) Scope? (/FOR-TOK Bounds)? +NT-SatisfiabilityDecl : Name /COLON-TOK /ASSERT-TOK NT-Expr /IS-TOK (SAT-TOK | UNSAT-TOK | FORGE_ERROR-TOK) Scope? (/FOR-TOK Bounds)? + | /ASSERT-TOK NT-Expr /IS-TOK (SAT-TOK | UNSAT-TOK | FORGE_ERROR-TOK) Scope? (/FOR-TOK Bounds)? -PropertyDecl : Name /COLON-TOK /ASSERT-TOK Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name Scope? (/FOR-TOK Bounds)? - | /ASSERT-TOK Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name Scope? (/FOR-TOK Bounds)? +NT-PropertyDecl : Name /COLON-TOK /ASSERT-TOK NT-Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name Scope? (/FOR-TOK Bounds)? + | /ASSERT-TOK NT-Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name Scope? (/FOR-TOK Bounds)? -QuantifiedPropertyDecl : Name /COLON-TOK /ASSERT-TOK /ALL-TOK DISJ-TOK? QuantDeclList /BAR-TOK Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name (/LEFT-SQUARE-TOK ExprList /RIGHT-SQUARE-TOK)? Scope? (/FOR-TOK Bounds)? - | /ASSERT-TOK /ALL-TOK DISJ-TOK? QuantDeclList /BAR-TOK Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name (/LEFT-SQUARE-TOK ExprList /RIGHT-SQUARE-TOK)? Scope? (/FOR-TOK Bounds)? +NT-QuantifiedPropertyDecl : Name /COLON-TOK /ASSERT-TOK /ALL-TOK DISJ-TOK? QuantDeclList /BAR-TOK NT-Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name (/LEFT-SQUARE-TOK ExprList /RIGHT-SQUARE-TOK)? Scope? (/FOR-TOK Bounds)? + | /ASSERT-TOK /ALL-TOK DISJ-TOK? QuantDeclList /BAR-TOK NT-Expr /IS-TOK (SUFFICIENT-TOK | NECESSARY-TOK) /FOR-TOK Name (/LEFT-SQUARE-TOK ExprList /RIGHT-SQUARE-TOK)? Scope? (/FOR-TOK Bounds)? -ConsistencyDecl: Name /COLON-TOK /ASSERT-TOK Expr /IS-TOK (CONSISTENT-TOK | INCONSISTENT-TOK) /WITH-TOK Name Scope? (/FOR-TOK Bounds)? - | /ASSERT-TOK Expr /IS-TOK (CONSISTENT-TOK | INCONSISTENT-TOK) /WITH-TOK Name Scope? (/FOR-TOK Bounds)? +NT-ConsistencyDecl: Name /COLON-TOK /ASSERT-TOK NT-Expr /IS-TOK (CONSISTENT-TOK | INCONSISTENT-TOK) /WITH-TOK Name Scope? (/FOR-TOK Bounds)? + | /ASSERT-TOK NT-Expr /IS-TOK (CONSISTENT-TOK | INCONSISTENT-TOK) /WITH-TOK Name Scope? (/FOR-TOK Bounds)? -TestSuiteDecl : /TEST-TOK /SUITE-TOK /FOR-TOK Name /LEFT-CURLY-TOK TestConstruct* /RIGHT-CURLY-TOK +NT-TestSuiteDecl : /TEST-TOK /SUITE-TOK /FOR-TOK Name /LEFT-CURLY-TOK TestConstruct* /RIGHT-CURLY-TOK -@TestConstruct : ExampleDecl | TestExpectDecl | PropertyDecl | QuantifiedPropertyDecl | SatisfiabilityDecl | ConsistencyDecl +@TestConstruct : NT-ExampleDecl | NT-TestExpectDecl | NT-PropertyDecl | NT-QuantifiedPropertyDecl + | NT-SatisfiabilityDecl | NT-ConsistencyDecl # UnOp : Mult @@ -128,12 +129,12 @@ TestSuiteDecl : /TEST-TOK /SUITE-TOK /FOR-TOK Name /LEFT-CURLY-TOK TestConstruct # | PLUS-TOK | MINUS-TOK | PPLUS-TOK | DOT-TOK | SUBT-TOK | SUPT-TOK ArrowOp : (@Mult | SET-TOK)? ARROW-TOK (@Mult | SET-TOK)? CompareOp : IN-TOK | EQ-TOK | LT-TOK | GT-TOK | LEQ-TOK | GEQ-TOK | IS-TOK | NI-TOK -LetDecl : @Name /EQ-TOK Expr -Block : /LEFT-CURLY-TOK Expr* /RIGHT-CURLY-TOK -BlockOrBar : Block | BAR-TOK Expr +LetDecl : @Name /EQ-TOK NT-Expr +NT-Block : /LEFT-CURLY-TOK NT-Expr* /RIGHT-CURLY-TOK +BlockOrBar : NT-Block | BAR-TOK NT-Expr Quant : ALL-TOK | NO-TOK | SUM-TOK | @Mult QualName : (THIS-TOK /SLASH-TOK)? (@Name /SLASH-TOK)* @Name | INT-TOK | SUM-TOK -OptionDecl : /OPTION-TOK QualName (QualName | PATH-OR-STR-TOK | MINUS-TOK? Number) +NT-OptionDecl : /OPTION-TOK QualName (QualName | PATH-OR-STR-TOK | MINUS-TOK? Number) Name : IDENTIFIER-TOK NameList : @Name @@ -155,8 +156,8 @@ LetDeclList : LetDecl | LetDecl /COMMA-TOK @LetDeclList TypescopeList : Typescope | Typescope /COMMA-TOK @TypescopeList -ExprList : Expr - | Expr /COMMA-TOK @ExprList +ExprList : NT-Expr + | NT-Expr /COMMA-TOK @ExprList ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This chain of productions enforces operator precedence in brag. @@ -195,49 +196,49 @@ ExprList : Expr ; implication and sequence, which associate to the right, and of ; binary temporal connectives which are not associative." -Expr : @Expr1 +NT-Expr : @NT-Expr1 | LET-TOK LetDeclList BlockOrBar | BIND-TOK LetDeclList BlockOrBar | Quant DISJ-TOK? QuantDeclList BlockOrBar -Expr1 : @Expr1.5 | Expr1 OR-TOK Expr1.5 -Expr1.5 : @Expr2 | Expr1.5 XOR-TOK Expr2 -Expr2 : @Expr3 | Expr2 IFF-TOK Expr3 +NT-Expr1 : @NT-Expr1.5 | NT-Expr1 OR-TOK NT-Expr1.5 +NT-Expr1.5 : @NT-Expr2 | NT-Expr1.5 XOR-TOK NT-Expr2 +NT-Expr2 : @NT-Expr3 | NT-Expr2 IFF-TOK NT-Expr3 ;; right assoc -Expr3 : @Expr4 | Expr4 IMP-TOK Expr3 (ELSE-TOK Expr3)? -Expr4 : @Expr4.5 | Expr4 AND-TOK Expr4.5 +NT-Expr3 : @NT-Expr4 | NT-Expr4 IMP-TOK NT-Expr3 (ELSE-TOK NT-Expr3)? +NT-Expr4 : @NT-Expr4.5 | NT-Expr4 AND-TOK NT-Expr4.5 ; Electrum binary operators (not associative) -Expr4.5 : @Expr5 | Expr5 UNTIL-TOK Expr5 - | Expr5 RELEASE-TOK Expr5 - | Expr5 SINCE-TOK Expr5 - | Expr5 TRIGGERED-TOK Expr5 -Expr5 : @Expr6 | NEG-TOK Expr5 - | ALWAYS-TOK Expr5 - | EVENTUALLY-TOK Expr5 - | AFTER-TOK Expr5 - | BEFORE-TOK Expr5 - | ONCE-TOK Expr5 - | HISTORICALLY-TOK Expr5 -Expr6 : @Expr7 | Expr6 NEG-TOK? CompareOp Expr7 -Expr7 : @Expr8 | (NO-TOK | SOME-TOK | LONE-TOK | ONE-TOK | TWO-TOK | SET-TOK) Expr8 -Expr8 : @Expr9 | Expr8 (PLUS-TOK | MINUS-TOK) Expr10 -Expr9 : @Expr10 | CARD-TOK Expr9 -Expr10 : @Expr11 | Expr10 PPLUS-TOK Expr11 -Expr11 : @Expr12 | Expr11 AMP-TOK Expr12 -Expr12 : @Expr13 | Expr12 ArrowOp Expr13 -Expr13 : @Expr14 | Expr13 (SUBT-TOK | SUPT-TOK) Expr14 -Expr14 : @Expr15 | Expr14 LEFT-SQUARE-TOK ExprList RIGHT-SQUARE-TOK -Expr15 : @Expr16 | Expr15 DOT-TOK Expr16 +NT-Expr4.5 : @NT-Expr5 | NT-Expr5 UNTIL-TOK NT-Expr5 + | NT-Expr5 RELEASE-TOK NT-Expr5 + | NT-Expr5 SINCE-TOK NT-Expr5 + | NT-Expr5 TRIGGERED-TOK NT-Expr5 +NT-Expr5 : @NT-Expr6 | NEG-TOK NT-Expr5 + | ALWAYS-TOK NT-Expr5 + | EVENTUALLY-TOK NT-Expr5 + | AFTER-TOK NT-Expr5 + | BEFORE-TOK NT-Expr5 + | ONCE-TOK NT-Expr5 + | HISTORICALLY-TOK NT-Expr5 +NT-Expr6 : @NT-Expr7 | NT-Expr6 NEG-TOK? CompareOp NT-Expr7 +NT-Expr7 : @NT-Expr8 | (NO-TOK | SOME-TOK | LONE-TOK | ONE-TOK | TWO-TOK | SET-TOK) NT-Expr8 +NT-Expr8 : @NT-Expr9 | NT-Expr8 (PLUS-TOK | MINUS-TOK) NT-Expr10 +NT-Expr9 : @NT-Expr10 | CARD-TOK NT-Expr9 +NT-Expr10 : @NT-Expr11 | NT-Expr10 PPLUS-TOK NT-Expr11 +NT-Expr11 : @NT-Expr12 | NT-Expr11 AMP-TOK NT-Expr12 +NT-Expr12 : @NT-Expr13 | NT-Expr12 ArrowOp NT-Expr13 +NT-Expr13 : @NT-Expr14 | NT-Expr13 (SUBT-TOK | SUPT-TOK) NT-Expr14 +NT-Expr14 : @NT-Expr15 | NT-Expr14 LEFT-SQUARE-TOK ExprList RIGHT-SQUARE-TOK +NT-Expr15 : @NT-Expr16 | NT-Expr15 DOT-TOK NT-Expr16 | Name LEFT-SQUARE-TOK ExprList RIGHT-SQUARE-TOK -Expr16 : @Expr17 | Expr16 PRIME-TOK -Expr17 : @Expr18 | (TILDE-TOK | EXP-TOK | STAR-TOK) Expr17 -Expr18 : Const +NT-Expr16 : @NT-Expr17 | NT-Expr16 PRIME-TOK +NT-Expr17 : @NT-Expr18 | (TILDE-TOK | EXP-TOK | STAR-TOK) NT-Expr17 +NT-Expr18 : Const | QualName | AT-TOK Name | BACKQUOTE-TOK Name | THIS-TOK | LEFT-CURLY-TOK QuantDeclList BlockOrBar RIGHT-CURLY-TOK - | /LEFT-PAREN-TOK @Expr /RIGHT-PAREN-TOK - | Block + | /LEFT-PAREN-TOK @NT-Expr /RIGHT-PAREN-TOK + | NT-Block | Sexpr ArrowExpr : QualName @@ -247,7 +248,7 @@ ArrowExpr : QualName ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Escape to forge/core -SexprDecl : Sexpr +NT-SexprDecl : Sexpr Sexpr : SEXPR-TOK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -258,24 +259,24 @@ Sexpr : SEXPR-TOK ;InstanceDecl : INSTANCE-TOK ; Partial `inst` declaration -InstDecl : /INST-TOK Name Bounds Scope? +NT-InstDecl : /INST-TOK Name Bounds Scope? ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Productions for the evaluation-request case ; i.e., this isn't a Forge model, but rather a query ; from the evaluator: -EvalRelDecl : ArrowDecl -EvalDecl : EVAL-TOK Expr +NT-EvalRelDecl : ArrowDecl +NT-EvalDecl : EVAL-TOK NT-Expr ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Bounds : EXACTLY-TOK? @ExprList ; | EXACTLY-TOK? @Block -ExampleDecl : /EXAMPLE-TOK Name /IS-TOK Expr /FOR-TOK Bounds +NT-ExampleDecl : /EXAMPLE-TOK Name /IS-TOK NT-Expr /FOR-TOK Bounds ; ??? used where? -QueryDecl : @Name /COLON-TOK ArrowExpr /EQ-TOK Expr +NT-QueryDecl : @Name /COLON-TOK ArrowExpr /EQ-TOK NT-Expr ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/forge/lang/expander.rkt b/forge/lang/expander.rkt index 1dc94294..ac161507 100644 --- a/forge/lang/expander.rkt +++ b/forge/lang/expander.rkt @@ -3,6 +3,17 @@ ; The #lang forge reader produces a module referencing this one as its module-path: ; https://docs.racket-lang.org/reference/module.html +; Internal-use-only macros defined in this module need to be available to the module +; syntax produced by the Forge language reader. Thus, there is potential identifier +; clash if such macros are named valid Forge identifiers (sig names, etc.) +; To avoid this, all macro names should contain a hyphen. This renders the name +; unusable as an identifier in Forge languages, which use - as set subtraction. +; This is why the parser names its non-terminals with "NT-" prefixes. + +; *** NOTE WELL *** +; If adding new expander macros or parser non-terminals, make sure to add a case to +; the tests/forge/other/internal-id-sigs.frg and internal-id-preds.frg test files. + (require syntax/parse/define racket/stxparam (for-syntax racket/base syntax/parse racket/syntax syntax/parse/define racket/function syntax/srcloc racket/match racket/list @@ -11,7 +22,10 @@ syntax/srcloc (only-in racket/list flatten) ; Needed because the abstract-tok definition below requires phase 2 - (for-syntax (for-syntax racket/base))) + (for-syntax (for-syntax racket/base)) + + (only-in forge/server/eval-model ->string) + racket/string) (require (only-in racket empty? first) (prefix-in @ (only-in racket +))) @@ -93,11 +107,11 @@ ; Import : OPEN-TOK QualName (LEFT-SQUARE-TOK QualNameList RIGHT-SQUARE-TOK)? (AS-TOK Name)? (define-syntax-class ImportClass - (pattern ((~datum Import) + (pattern ((~datum NT-Import) import-name:QualNameClass (~optional (~seq "[" other-names:QualNameListClass "]")) (~optional (~seq "as" as-name:NameClass)))) - (pattern ((~datum Import) + (pattern ((~datum NT-Import) file-path:str (~optional (~seq "as" as-name:NameClass))))) @@ -106,7 +120,7 @@ ; EvalDecl : EVAL-TOK Expr (define-syntax-class EvalDeclClass - (pattern ((~datum EvalDecl) + (pattern ((~datum NT-EvalDecl) "eval" exp:ExprClass))) @@ -145,7 +159,7 @@ ; SigDecl : VAR-TOK? ABSTRACT-TOK? Mult? /SIG-TOK NameList SigExt? /LEFT-CURLY-TOK ArrowDeclList? /RIGHT-CURLY-TOK Block? (define-syntax-class SigDeclClass - (pattern ((~datum SigDecl) + (pattern ((~datum NT-SigDecl) (~optional isv:VarKeywordClass #:defaults ([isv #'#f])) (~optional abstract:abstract-tok) (~optional mult:MultClass) @@ -272,7 +286,7 @@ ; PredDecl : /PRED-TOK (QualName DOT-TOK)? Name ParaDecls? Block (define-syntax-class PredDeclClass #:description "predicate declaration" - (pattern ((~datum PredDecl) + (pattern ((~datum NT-PredDecl) (~optional _:PredTypeClass) (~optional (~seq prefix:QualNameClass ".")) name:NameClass @@ -282,7 +296,7 @@ ; FunDecl : /FUN-TOK (QualName DOT-TOK)? Name ParaDecls? /COLON-TOK Expr Block (define-syntax-class FunDeclClass #:description "helper function declaration" - (pattern ((~datum FunDecl) + (pattern ((~datum NT-FunDecl) (~optional (~seq prefix:QualNameClass ".")) name:NameClass (~optional decls:ParaDeclsClass) @@ -315,13 +329,13 @@ ; AssertDecl : /ASSERT-TOK Name? Block (define-syntax-class AssertDeclClass - (pattern ((~datum AssertDecl) + (pattern ((~datum NT-AssertDecl) (~optional name:NameClass) block:BlockClass))) ; CmdDecl : (Name /COLON-TOK)? (RUN-TOK | CHECK-TOK) Parameters? (QualName | Block)? Scope? (/FOR-TOK Bounds)? (define-syntax-class CmdDeclClass - (pattern ((~datum CmdDecl) + (pattern ((~datum NT-CmdDecl) (~optional name:NameClass) (~or "run" "check") (~optional parameters:ParametersClass) @@ -333,7 +347,7 @@ ; TestDecl : (Name /COLON-TOK)? Parameters? (QualName | Block)? Scope? (/FOR-TOK Bounds)? /IS-TOK (SAT-TOK | UNSAT-TOK) (define-syntax-class TestDeclClass - (pattern ((~datum TestDecl) + (pattern ((~datum NT-TestDecl) (~optional name:NameClass) (~optional parameters:ParametersClass) (~optional (~or pred-name:QualNameClass @@ -349,7 +363,7 @@ ; TestExpectDecl : TEST-TOK? EXPECT-TOK Name? TestBlock (define-syntax-class TestExpectDeclClass - (pattern ((~datum TestExpectDecl) + (pattern ((~datum NT-TestExpectDecl) (~optional "test") "expect" (~optional name:NameClass) @@ -366,7 +380,7 @@ (define-syntax-class PropertyDeclClass #:attributes (tname prop pred-name constraint-type scope bounds) (pattern ( - (~datum PropertyDecl) + (~datum NT-PropertyDecl) (~optional -tname:NameClass) -prop:ExprClass (~and (~or "sufficient" "necessary") ct) @@ -382,7 +396,7 @@ (define-syntax-class QuantifiedPropertyDeclClass #:attributes (tname quant-decls disj prop pred-name pred-exprs constraint-type scope bounds) - (pattern ((~datum QuantifiedPropertyDecl) + (pattern ((~datum NT-QuantifiedPropertyDecl) (~optional -tname:NameClass) (~optional (~and "disj" -disj)) -quant-decls:DeclListClass @@ -404,7 +418,7 @@ (define-syntax-class SatisfiabilityDeclClass #:attributes (tname prop expected scope bounds) - (pattern ((~datum SatisfiabilityDecl) + (pattern ((~datum NT-SatisfiabilityDecl) (~optional -tname:NameClass) -prop:ExprClass (~and (~or "sat" "unsat" "forge_error") ct) @@ -419,7 +433,7 @@ (define-syntax-class ConsistencyDeclClass #:attributes (tname test-expr pred-name consistency expected scope bounds) - (pattern ((~datum ConsistencyDecl) + (pattern ((~datum NT-ConsistencyDecl) (~optional -tname:NameClass) -test-expr:ExprClass (~and (~or "consistent" "inconsistent") ct) @@ -436,13 +450,13 @@ (define-syntax-class TestSuiteDeclClass #:attributes (pred-name (test-constructs 1)) - (pattern ((~datum TestSuiteDecl) + (pattern ((~datum NT-TestSuiteDecl) -pred-name:NameClass test-constructs:TestConstructClass ...) #:with pred-name #'-pred-name.name)) (define-syntax-class ExampleDeclClass - (pattern ((~datum ExampleDecl) + (pattern ((~datum NT-ExampleDecl) (~optional name:NameClass) pred:ExprClass bounds:BoundsClass))) @@ -470,23 +484,23 @@ ; OptionDecl : /OPTION-TOK QualName (QualName | FILE-PATH-TOK | Number) (define-syntax-class OptionDeclClass #:attributes (n v) - (pattern ((~datum OptionDecl) name:QualNameClass value:QualNameClass) + (pattern ((~datum NT-OptionDecl) name:QualNameClass value:QualNameClass) #:attr n #'name.name #:attr v #'value.name) - (pattern ((~datum OptionDecl) name:QualNameClass value:str) + (pattern ((~datum NT-OptionDecl) name:QualNameClass value:str) #:attr n #'name.name #:attr v #'value) - (pattern ((~datum OptionDecl) name:QualNameClass value:NumberClass) + (pattern ((~datum NT-OptionDecl) name:QualNameClass value:NumberClass) #:attr n #'name.name #:attr v #'value.value) - (pattern ((~datum OptionDecl) name:QualNameClass "-" value:NumberClass) + (pattern ((~datum NT-OptionDecl) name:QualNameClass "-" value:NumberClass) #:attr n #'name.name #:attr v (quasisyntax #,(* -1 (syntax->datum #'value.value))))) ; Block : /LEFT-CURLY-TOK Expr* /RIGHT-CURLY-TOK (define-syntax-class BlockClass - (pattern ((~datum Block) + (pattern ((~datum NT-Block) exprs:ExprClass ...))) ; Name : IDENTIFIER-TOK @@ -530,7 +544,7 @@ ; SexprDecl : Sexpr (define-syntax-class SexprDeclClass - (pattern ((~datum SexprDecl) exp:SexprClass))) + (pattern ((~datum NT-SexprDecl) exp:SexprClass))) ; Sexpr : SEXPR-TOK (define-syntax-class SexprClass @@ -538,14 +552,14 @@ ; InstDecl : /INST-TOK Name Bounds Scope? (define-syntax-class InstDeclClass - (pattern ((~datum InstDecl) + (pattern ((~datum NT-InstDecl) name:NameClass bounds:BoundsClass (~optional scope:ScopeClass)))) ; RelDecl : ArrowDecl (define-syntax-class RelDeclClass - (pattern ((~datum RelDecl) decl:ArrowDeclClass))) + (pattern ((~datum NT-RelDecl) decl:ArrowDeclClass))) ; Parameters : /LeftAngle @QualNameList /RightAngle (define-syntax-class ParametersClass @@ -579,26 +593,26 @@ (define-syntax-class QualNameOrAtomOrAtomizedNumberClass #:description "name, atom name, or number" (pattern name:QualNameClass - #:attr translate (syntax/loc this-syntax (Expr name))) + #:attr translate (syntax/loc this-syntax (NT-Expr name))) (pattern ((~datum AtomNameOrNumber) "`" name:NameClass) - #:attr translate (syntax/loc this-syntax (Expr "`" name))) + #:attr translate (syntax/loc this-syntax (NT-Expr "`" name))) ; Negative numbers are now handled in the lexer, so that "- 1" is not transformed to "-1" (pattern ((~datum AtomNameOrNumber) num:NumberClass) #:attr translate - (quasisyntax/loc this-syntax (Expr #,(syntax/loc this-syntax (Const num)))))) + (quasisyntax/loc this-syntax (NT-Expr #,(syntax/loc this-syntax (Const num)))))) (define-syntax-class BoundLHSClass #:description "left-hand-side of a bind declaration" ; No join, relation name only on LHS (pattern ((~datum BoundLHS) target:QualNameClass) - #:attr translate (syntax/loc this-syntax (Expr target))) + #:attr translate (syntax/loc this-syntax (NT-Expr target))) ; Join, atom name dotted with field name (pattern ((~datum BoundLHS) ((~datum AtomNameOrNumber) "`" atom:NameClass) field:QualNameClass) #:attr translate (quasisyntax/loc this-syntax - (Expr - #,(syntax/loc this-syntax (Expr "`" atom)) "." - #,(syntax/loc this-syntax (Expr field)))))) + (NT-Expr + #,(syntax/loc this-syntax (NT-Expr "`" atom)) "." + #,(syntax/loc this-syntax (NT-Expr field)))))) (define-syntax-class BoundClass #:description "bind declaration" @@ -608,37 +622,37 @@ op:CompareOpClass rhs:BindRHSUnionClass) #:attr translate (begin - (quasisyntax/loc this-syntax (Expr lhs.translate op rhs.translate)))) + (quasisyntax/loc this-syntax (NT-Expr lhs.translate op rhs.translate)))) ; cardinality bound (single relation): #LHS = N (pattern ((~datum Bound) ; or backquote name ((~datum BoundLHS) "#" target:QualNameClass) op:CompareOpClass rhs:BindRHSUnionClass) - #:attr translate (with-syntax* ([tgt (syntax/loc #'target (Expr target))] - [left-subexpr (syntax/loc #'target (Expr "#" tgt))]) - (syntax/loc this-syntax (Expr left-subexpr op rhs.translate)))) + #:attr translate (with-syntax* ([tgt (syntax/loc #'target (NT-Expr target))] + [left-subexpr (syntax/loc #'target (NT-Expr "#" tgt))]) + (syntax/loc this-syntax (NT-Expr left-subexpr op rhs.translate)))) ; "no" bound: relation LHS and piecewise LHS (pattern ((~datum Bound) (~datum "no") ((~datum BoundLHS) target:QualNameClass)) - #:attr translate (with-syntax ([tgt (syntax/loc #'target (Expr target))]) - (syntax/loc this-syntax (Expr "no" tgt)))) + #:attr translate (with-syntax ([tgt (syntax/loc #'target (NT-Expr target))]) + (syntax/loc this-syntax (NT-Expr "no" tgt)))) (pattern ((~datum Bound) (~datum "no") ((~datum BoundLHS) ((~datum AtomNameOrNumber) "`" atom:NameClass) field:QualNameClass)) #:attr translate (quasisyntax/loc this-syntax - (Expr "no" + (NT-Expr "no" #,(quasisyntax/loc this-syntax - (Expr - #,(quasisyntax/loc this-syntax (Expr "`" atom)) "." - #,(quasisyntax/loc this-syntax (Expr field))))))) + (NT-Expr + #,(quasisyntax/loc this-syntax (NT-Expr "`" atom)) "." + #,(quasisyntax/loc this-syntax (NT-Expr field))))))) ; identifier: re-use of `inst` defined (pattern ((~datum Bound) name:QualNameClass) - #:attr translate (syntax/loc this-syntax (Expr name)))) + #:attr translate (syntax/loc this-syntax (NT-Expr name)))) (define-syntax-class BindRHSUnionClass #:description "union in right-hand-side of a bind declaration" @@ -650,11 +664,11 @@ (pattern ((~datum BindRHSUnion) tups:BindRHSUnionClass tup:BindRHSProductClass) - #:attr translate (syntax/loc this-syntax (Expr tups.translate "+" tup.translate))) + #:attr translate (syntax/loc this-syntax (NT-Expr tups.translate "+" tup.translate))) (pattern ((~datum BindRHSUnion) tups1:BindRHSUnionClass tups2:BindRHSUnionClass) - #:attr translate (syntax/loc this-syntax (Expr tups1.translate "+" tups2.translate)))) + #:attr translate (syntax/loc this-syntax (NT-Expr tups1.translate "+" tups2.translate)))) (define-syntax-class BindRHSProductClass #:description "product in right-hand-side of a bind declaration" @@ -669,21 +683,21 @@ (pattern ((~datum BindRHSProduct) tup:BindRHSProductClass atom:QualNameOrAtomOrAtomizedNumberClass) - #:attr translate (syntax/loc this-syntax (Expr tup.translate (ArrowOp "->") atom.translate))) + #:attr translate (syntax/loc this-syntax (NT-Expr tup.translate (ArrowOp "->") atom.translate))) (pattern ((~datum BindRHSProduct) atom:QualNameOrAtomOrAtomizedNumberClass tup:BindRHSProductClass) - #:attr translate (syntax/loc this-syntax (Expr atom.translate (ArrowOp "->") tup.translate))) + #:attr translate (syntax/loc this-syntax (NT-Expr atom.translate (ArrowOp "->") tup.translate))) ; "union -> product" or "product -> union" (pattern ((~datum BindRHSProduct) union1:BindRHSUnionClass product2:BindRHSProductClass) - #:attr translate (syntax/loc this-syntax (Expr union1.translate (ArrowOp "->") product2.translate))) + #:attr translate (syntax/loc this-syntax (NT-Expr union1.translate (ArrowOp "->") product2.translate))) (pattern ((~datum BindRHSProduct) product1:BindRHSProductClass union2:BindRHSUnionClass) - #:attr translate (syntax/loc this-syntax (Expr product1.translate (ArrowOp "->") union2.translate)))) + #:attr translate (syntax/loc this-syntax (NT-Expr product1.translate (ArrowOp "->") union2.translate)))) ; EXPRESSIONS @@ -802,11 +816,12 @@ #:attr symbol (syntax/loc #'q sum-quant))) (define-syntax-class ExprClass - (pattern ((~or (~datum Expr) (~datum Expr1) (~datum Expr1.5) (~datum Expr2) (~datum Expr3) - (~datum Expr4) (~datum Expr4.5) (~datum Expr5) (~datum Expr6) (~datum Expr7) (~datum Expr7.5) - (~datum Expr8) (~datum Expr9) (~datum Expr10) (~datum Expr11) - (~datum Expr12) (~datum Expr13) (~datum Expr14) (~datum Expr15) - (~datum Expr16) (~datum Expr17)) + (pattern ((~or (~datum NT-Expr) (~datum NT-Expr1) (~datum NT-Expr1.5) (~datum NT-Expr2) + (~datum NT-Expr3) (~datum NT-Expr4) (~datum NT-Expr4.5) (~datum NT-Expr5) + (~datum NT-Expr6) (~datum NT-Expr7) (~datum NT-Expr7.5) + (~datum NT-Expr8) (~datum NT-Expr9) (~datum NT-Expr10) (~datum NT-Expr11) + (~datum NT-Expr12) (~datum NT-Expr13) (~datum NT-Expr14) (~datum NT-Expr15) + (~datum NT-Expr16) (~datum NT-Expr17)) _ ...))) ; ExprList : Expr @@ -818,9 +833,9 @@ ; AlloyModule : ModuleDecl? Import* Paragraph* ; | EvalDecl* -(define-syntax (AlloyModule stx) +(define-syntax (NT-AlloyModule stx) (syntax-parse stx - [((~datum AlloyModule) (~optional module-decl:ModuleDeclClass) + [((~datum NT-AlloyModule) (~optional module-decl:ModuleDeclClass) (~seq import:ImportClass ...) (~seq paragraph:ParagraphClass ...)) (syntax/loc stx @@ -828,28 +843,29 @@ (~? module-decl) import ... paragraph ...))] - [((~datum AlloyModule) ((~datum EvalDecl) "eval" expr:ExprClass)) + [((~datum NT-AlloyModule) ((~datum NT-EvalDecl) "eval" expr:ExprClass)) (syntax/loc stx expr)] - [((~datum AlloyModule) ((~datum EvalDecl) "eval" expr:ExprClass) ...+) - (syntax/loc stx (raise "Can't eval multiple expressions."))])) + [((~datum NT-AlloyModule) ((~datum NT-EvalDecl) "eval" expr:ExprClass) ...+) + (quasisyntax/loc stx (raise-forge-error #:msg "Can't eval multiple expressions." + #:context #,(build-source-location stx)))])) ; ModuleDecl : /MODULE-TOK QualName (LEFT-SQUARE-TOK NameList RIGHT-SQUARE-TOK)? -(define-syntax (ModuleDecl stx) +(define-syntax (NT-ModuleDecl stx) (syntax-parse stx - [((~datum ModuleDecl) module-name:QualNameClass + [((~datum NT-ModuleDecl) module-name:QualNameClass (~optional (~seq "[" other-names:NameListClass "]"))) - (syntax/loc stx (raise "ModuleDecl not yet implemented."))])) + (syntax/loc stx (raise "Forge does not yet support Alloy-style module naming."))])) ; Import : OPEN-TOK QualName (LEFT-SQUARE-TOK QualNameList RIGHT-SQUARE-TOK)? (AS-TOK Name)? -(define-syntax (Import stx) +(define-syntax (NT-Import stx) (syntax-parse stx - [((~datum Import) file-path:str + [((~datum NT-Import) file-path:str (~optional (~seq "as" as-name:NameClass))) (syntax/loc stx (begin (~? (require (prefix-in as-name.name file-path)) (require file-path))))] - [((~datum Import) import-name:QualNameClass + [((~datum NT-Import) import-name:QualNameClass (~optional (~seq "[" other-names:QualNameListClass "]")) (~optional (~seq "as" as-name:NameClass))) (syntax/loc stx (begin @@ -858,9 +874,9 @@ (~? (raise (format "Importing as not yet implemented. ~a" 'as-name)))))])) ; SigDecl : VAR-TOK? ABSTRACT-TOK? Mult? /SIG-TOK NameList SigExt? /LEFT-CURLY-TOK ArrowDeclList? /RIGHT-CURLY-TOK Block? -(define-syntax (SigDecl stx) +(define-syntax (NT-SigDecl stx) (syntax-parse stx - [((~datum SigDecl) (~optional isv:VarKeywordClass #:defaults ([isv #'#f])) + [((~datum NT-SigDecl) (~optional isv:VarKeywordClass #:defaults ([isv #'#f])) (~optional abstract:abstract-tok) (~optional mult:MultClass) sig-names:NameListClass @@ -876,7 +892,7 @@ (~? (~@ #:is-var isv)) (~? (~@ extends.symbol extends.value))))))))] - [((~datum SigDecl) (~optional isv:VarKeywordClass #:defaults ([isv #'#f])) + [((~datum NT-SigDecl) (~optional isv:VarKeywordClass #:defaults ([isv #'#f])) (~optional abstract:abstract-tok) (~optional mult:MultClass) sig-names:NameListClass @@ -927,9 +943,9 @@ (syntax/loc stx (raise "Facts are not allowed in #lang forge."))])) ; PredDecl : /PRED-TOK (QualName DOT-TOK)? Name ParaDecls? Block -(define-syntax (PredDecl stx) +(define-syntax (NT-PredDecl stx) (syntax-parse stx - [((~datum PredDecl) (~optional pt:PredTypeClass) + [((~datum NT-PredDecl) (~optional pt:PredTypeClass) (~optional (~seq prefix:QualNameClass ".")) name:NameClass block:BlockClass) @@ -939,7 +955,7 @@ ; preserve stx location in Racket *sub*expression #,(syntax/loc stx (pred (~? pt.kw) (#:lang (get-check-lang)) name.name block)))))] - [((~datum PredDecl) (~optional pt:PredTypeClass) + [((~datum NT-PredDecl) (~optional pt:PredTypeClass) (~optional (~seq prefix:QualNameClass ".")) name:NameClass decls:ParaDeclsClass @@ -955,12 +971,12 @@ #,(syntax/loc stx (pred (~? pt.kw) (#:lang (get-check-lang)) decl block)))))])) ; FunDecl : /FUN-TOK (QualName DOT-TOK)? Name ParaDecls? /COLON-TOK Expr Block -(define-syntax (FunDecl stx) +(define-syntax (NT-FunDecl stx) (syntax-parse stx ; TODO: output type declared is currently being lost ; 0-ary function - [((~datum FunDecl) (~optional (~seq prefix:QualNameClass ".")) + [((~datum NT-FunDecl) (~optional (~seq prefix:QualNameClass ".")) name:NameClass (~optional output-mult:HelperMultClass) output-expr:ExprClass @@ -972,7 +988,7 @@ (const name.name body))))] ; >0-ary function - [((~datum FunDecl) (~optional (~seq prefix:QualNameClass ".")) + [((~datum NT-FunDecl) (~optional (~seq prefix:QualNameClass ".")) name:NameClass decls:ParaDeclsClass (~optional output-mult:HelperMultClass #:defaults ([output-mult #'#f])) @@ -993,10 +1009,11 @@ (fun decl body #:codomain output))))])) ; AssertDecl : /ASSERT-TOK Name? Block -(define-syntax (AssertDecl stx) +(define-syntax (NT-AssertDecl stx) (syntax-parse stx - [((~datum AssertDecl) _ ...) - (syntax/loc stx (raise "Assertions not yet implemented."))])) + [((~datum NT-AssertDecl) _ ...) + (quasisyntax/loc stx (raise-forge-error #:msg "Alloy-style assertions are not supported in Forge; use `assert {...} is unsat` instead." + #:context #,(build-source-location stx)))])) (define-for-syntax make-temporary-name (let ((name-counter (box 1))) @@ -1022,9 +1039,9 @@ (string->symbol (format "temporary-name_~a_~a" source_disambiguator curr-num))))) ; CmdDecl : (Name /COLON-TOK)? (RUN-TOK | CHECK-TOK) Parameters? (QualName | Block)? Scope? (/FOR-TOK Bounds)? -(define-syntax (CmdDecl stx) +(define-syntax (NT-CmdDecl stx) (syntax-parse stx - [((~datum CmdDecl) (~optional name:NameClass) + [((~datum NT-CmdDecl) (~optional name:NameClass) (~and cmd-type (~or "run" "check")) (~optional parameters:ParametersClass) (~optional (~or pred:QualNameClass @@ -1050,12 +1067,12 @@ ))])) ; TestDecl : (Name /COLON-TOK)? Parameters? (QualName | Block)? Scope? (/FOR-TOK Bounds)? /IS-TOK (SAT-TOK | UNSAT-TOK) -(define-syntax (TestDecl stx) +(define-syntax (NT-TestDecl stx) ; This stx object currently has the location of the enclosing TestBlock ; ... unless there is a name provided? (already, at this point, even before the parse below) ;(printf "expander for TestDecl: ~a~n" stx) (syntax-parse stx - [((~datum TestDecl) (~optional name:NameClass) + [((~datum NT-TestDecl) (~optional name:NameClass) (~optional parameters:ParametersClass) (~optional (~or pred:QualNameClass preds:BlockClass)) @@ -1076,10 +1093,10 @@ (~? (~@ #:expect-details expected-details)))))])) ; TestExpectDecl : TEST-TOK? EXPECT-TOK Name? TestBlock -(define-syntax (TestExpectDecl stx) +(define-syntax (NT-TestExpectDecl stx) ;(printf "expander for TestExpectDecl: ~a~n" stx) (syntax-parse stx - [((~datum TestExpectDecl) (~optional (~and "test" test-tok)) + [((~datum NT-TestExpectDecl) (~optional (~and "test" test-tok)) "expect" (~optional name:NameClass) block:TestBlockClass) @@ -1088,7 +1105,7 @@ (syntax/loc stx (begin)))])) -(define-syntax (PropertyDecl stx) +(define-syntax (NT-PropertyDecl stx) (syntax-parse stx [pwd:PropertyDeclClass #:with imp_total (if (eq? (syntax-e #'pwd.constraint-type) 'sufficient) @@ -1107,7 +1124,7 @@ #:bounds pwd.bounds #:expect checked ))])) -(define-syntax (QuantifiedPropertyDecl stx) +(define-syntax (NT-QuantifiedPropertyDecl stx) (syntax-parse stx [qpd:QuantifiedPropertyDeclClass ;;;#:do [(printf "QuantifiedPropertyDeclClass.PropExprs: ~a~n" (syntax->datum #'qpd.prop-exprs))] @@ -1137,7 +1154,7 @@ #:expect checked )))])) -(define-syntax (SatisfiabilityDecl stx) +(define-syntax (NT-SatisfiabilityDecl stx) (syntax-parse stx [sd:SatisfiabilityDeclClass #:with test_name (if (equal? (syntax-e #'sd.tname) "") @@ -1151,7 +1168,7 @@ #:bounds sd.bounds #:expect sd.expected ))])) -(define-syntax (ConsistencyDecl stx) +(define-syntax (NT-ConsistencyDecl stx) (syntax-parse stx [cd:ConsistencyDeclClass #:with test_name (if (equal? (syntax-e #'cd.tname) "") @@ -1181,7 +1198,7 @@ (syntax-source ex) (syntax-line ex) (syntax-column ex) tp)))) -(define-syntax (TestSuiteDecl stx) +(define-syntax (NT-TestSuiteDecl stx) (syntax-parse stx [tsd:TestSuiteDeclClass @@ -1193,9 +1210,9 @@ (begin tsd.test-constructs ...))])) -(define-syntax (ExampleDecl stx) +(define-syntax (NT-ExampleDecl stx) (syntax-parse stx - [((~datum ExampleDecl) (~optional name:NameClass) + [((~datum NT-ExampleDecl) (~optional name:NameClass) pred:ExprClass bounds:BoundsClass) (quasisyntax/loc stx @@ -1216,7 +1233,7 @@ ; OptionDecl : /OPTION-TOK QualName (QualName | FILE-PATH-TOK | Number) -(define-syntax (OptionDecl stx) +(define-syntax (NT-OptionDecl stx) (syntax-parse stx [dec:OptionDeclClass ; Some options contain file paths. By saving the path of the .frg file at a point @@ -1226,9 +1243,9 @@ ])) ; InstDecl : /INST-TOK Name Bounds Scope? -(define-syntax (InstDecl stx) +(define-syntax (NT-InstDecl stx) (syntax-parse stx - [((~datum InstDecl) + [((~datum NT-InstDecl) name:NameClass bounds:BoundsClass (~optional scope:ScopeClass)) @@ -1276,115 +1293,115 @@ #:context stx)])) ; Block : /LEFT-CURLY-TOK Expr* /RIGHT-CURLY-TOK -(define-syntax (Block stx) +(define-syntax (NT-Block stx) (syntax-parse stx - [((~datum Block) exprs:ExprClass ...) + [((~datum NT-Block) exprs:ExprClass ...) (with-syntax ([(exprs ...) (syntax->list #'(exprs ...))]) (quasisyntax/loc stx (disambiguate-block (list exprs ...) #:stx #,(build-source-location stx))))])) -(define-syntax (Expr stx) +(define-syntax (NT-Expr stx) ;(printf "Debug: Expr: ~a~n" stx) (syntax-parse stx - [((~datum Expr) "let" decls:LetDeclListClass bob:BlockOrBarClass) + [((~datum NT-Expr) "let" decls:LetDeclListClass bob:BlockOrBarClass) (syntax/loc stx (let decls.translate bob.exprs))] - [((~datum Expr) "bind" decls:LetDeclListClass bob:BlockOrBarClass) + [((~datum NT-Expr) "bind" decls:LetDeclListClass bob:BlockOrBarClass) (syntax/loc stx (raise "bind not implemented."))] ; Quantifier - [((~datum Expr) q:QuantClass decls:DeclListClass bob:BlockOrBarClass) + [((~datum NT-Expr) q:QuantClass decls:DeclListClass bob:BlockOrBarClass) (syntax/loc stx (q.symbol decls.translate bob.exprs))] ; stx, not #'q ; Quantifier with disj - [((~datum Expr) q:QuantClass "disj" decls:DeclListClass bob:BlockOrBarClass) + [((~datum NT-Expr) q:QuantClass "disj" decls:DeclListClass bob:BlockOrBarClass) (syntax/loc stx (q.symbol #:disj decls.translate bob.exprs))] ; stx, not #'q - [((~datum Expr) expr1:ExprClass (~or "or" "||") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "or" "||") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (|| expr1 expr2)))] ; exclusive OR - [((~datum Expr) expr1:ExprClass "xor" expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass "xor" expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (xor expr1 expr2)))] - [((~datum Expr) expr1:ExprClass (~or "iff" "<=>") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "iff" "<=>") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (iff (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass (~or "implies" "=>") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "implies" "=>") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (implies (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass (~or "implies" "=>") expr2:ExprClass + [((~datum NT-Expr) expr1:ExprClass (~or "implies" "=>") expr2:ExprClass "else" expr3:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)] [expr3 (my-expand #'expr3)]) (syntax/loc stx (ifte expr1 expr2 expr3)))] - [((~datum Expr) expr1:ExprClass (~or "and" "&&") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "and" "&&") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (&& expr1 expr2)))] - [((~datum Expr) expr1:ExprClass (~or "releases") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "releases") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (releases expr1 expr2)))] - [((~datum Expr) expr1:ExprClass (~or "until") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "until") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (until expr1 expr2)))] - [((~datum Expr) expr1:ExprClass (~or "since") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "since") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (since expr1 expr2)))] - [((~datum Expr) expr1:ExprClass (~or "triggered") expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass (~or "triggered") expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (triggered expr1 expr2)))] - [((~datum Expr) (~or "!" "not") expr1:ExprClass) + [((~datum NT-Expr) (~or "!" "not") expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (! (#:lang (get-check-lang)) expr1)))] - [((~datum Expr) (~or "always") expr1:ExprClass) + [((~datum NT-Expr) (~or "always") expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (always expr1)))] - [((~datum Expr) (~or "eventually") expr1:ExprClass) + [((~datum NT-Expr) (~or "eventually") expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (eventually expr1)))] - [((~datum Expr) (~or "next_state") expr1:ExprClass) + [((~datum NT-Expr) (~or "next_state") expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (next_state expr1)))] - [((~datum Expr) (~or "historically") expr1:ExprClass) + [((~datum NT-Expr) (~or "historically") expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (historically expr1)))] - [((~datum Expr) (~or "once") expr1:ExprClass) + [((~datum NT-Expr) (~or "once") expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (once expr1)))] - [((~datum Expr) (~or "prev_state") expr1:ExprClass) + [((~datum NT-Expr) (~or "prev_state") expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (prev_state expr1)))] - [((~datum Expr) expr1:ExprClass op:CompareOpClass expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass op:CompareOpClass expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)] [op #'op.symbol]) (syntax/loc stx (op (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass + [((~datum NT-Expr) expr1:ExprClass (~or "!" "not") op:CompareOpClass expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] @@ -1394,23 +1411,23 @@ (quasisyntax/loc stx (! #,(syntax/loc stx (op (#:lang (get-check-lang)) expr1 expr2)))))] ; Multiplicity form - [((~datum Expr) (~and (~or "no" "some" "lone" "one" "two" "set") + [((~datum NT-Expr) (~and (~or "no" "some" "lone" "one" "two" "set") op) expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [op (datum->syntax #'op (string->symbol (syntax->datum #'op)) #'op)]) (syntax/loc stx (op (#:lang (get-check-lang)) expr1)))] - [((~datum Expr) "#" expr1:ExprClass) + [((~datum NT-Expr) "#" expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (card (#:lang (get-check-lang)) expr1)))] ; Semantic priming as in Electrum - [((~datum Expr) expr1:ExprClass "'") + [((~datum NT-Expr) expr1:ExprClass "'") (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (prime (#:lang (get-check-lang)) expr1)))] - [((~datum Expr) expr1:ExprClass "+" expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass "+" expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)] [check-lang (if (forge-context=? '(inst example)) @@ -1418,22 +1435,22 @@ #'(get-check-lang))]) (syntax/loc stx (+ (#:lang check-lang) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass "-" expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass "-" expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (- (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass "++" expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass "++" expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (++ (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass "&" expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass "&" expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (& (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass op:ArrowOpClass expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass op:ArrowOpClass expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)] [check-lang (if (forge-context=? '(inst example)) @@ -1441,58 +1458,58 @@ #'(get-check-lang))]) (syntax/loc stx (-> (#:lang check-lang) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass ":>" expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass ":>" expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (:> (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) expr1:ExprClass "<:" expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass "<:" expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (<: (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) "[" exprs:ExprListClass "]") + [((~datum NT-Expr) "[" exprs:ExprListClass "]") (syntax/loc stx (raise (format "Unimplemented ~a" exprs)))] - [((~datum Expr) expr1:ExprClass "." expr2:ExprClass) + [((~datum NT-Expr) expr1:ExprClass "." expr2:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)] [expr2 (my-expand #'expr2)]) (syntax/loc stx (join (#:lang (get-check-lang)) expr1 expr2)))] - [((~datum Expr) name:NameClass "[" exprs:ExprListClass "]") + [((~datum NT-Expr) name:NameClass "[" exprs:ExprListClass "]") ; Is this production ever used? Both box join and helper use seem to use the Expr version below. ; (printf "expander: Name[Expr...]: ~a~n" #'name) (with-syntax ([name #'name.name] [(exprs ...) (datum->syntax #f (map my-expand (syntax->list #'(exprs.exprs ...))))]) (syntax/loc stx (name exprs ...)))] - [((~datum Expr) expr1orig:ExprClass "[" exprs:ExprListClass "]") + [((~datum NT-Expr) expr1orig:ExprClass "[" exprs:ExprListClass "]") ; This might be a helper function or predicate invocation (with arguments), or a box join. ; Note that expr1 might be a macro name *or* a procedure, so we can't necessarily "apply" it. (with-syntax ([expr1 (my-expand #'expr1orig)] [(exprs ...) (datum->syntax #f (map my-expand (syntax->list #'(exprs.exprs ...))))]) (syntax/loc stx (expr1 exprs ...)))] - [((~datum Expr) "~" expr1:ExprClass) + [((~datum NT-Expr) "~" expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (~ (#:lang (get-check-lang)) expr1)))] - [((~datum Expr) "^" expr1:ExprClass) + [((~datum NT-Expr) "^" expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (^ (#:lang (get-check-lang)) expr1)))] - [((~datum Expr) "*" expr1:ExprClass) + [((~datum NT-Expr) "*" expr1:ExprClass) (with-syntax ([expr1 (my-expand #'expr1)]) (syntax/loc stx (* (#:lang (get-check-lang)) expr1)))] - [((~datum Expr) const:ConstClass) + [((~datum NT-Expr) const:ConstClass) (syntax/loc stx const.translate)] ; If the name references an AST node, retain use-site location information ; rather than the location of the declaration. ; If it references a _macro_, such as `add`, `max`, etc. *don't* wrap it! - [((~datum Expr) name:QualNameClass) + [((~datum NT-Expr) name:QualNameClass) (define local-value (syntax-local-value #'name.name (lambda () #f))) ; (printf "local-value for ~a: ~a~n" #'name.name local-value) (if local-value @@ -1506,19 +1523,19 @@ (with-syntax ([loc (build-source-location (syntax/loc this-syntax #'1))]) (syntax/loc stx (correct-id-loc name.name #:loc loc))))] - [((~datum Expr) "this") + [((~datum NT-Expr) "this") (syntax/loc stx this)] - [((~datum Expr) "`" name:NameClass) + [((~datum NT-Expr) "`" name:NameClass) (syntax/loc stx (atom 'name.name))] - [((~datum Expr) "{" decls:DeclListClass bob:BlockOrBarClass "}") + [((~datum NT-Expr) "{" decls:DeclListClass bob:BlockOrBarClass "}") (syntax/loc stx (set (#:lang (get-check-lang)) decls.translate bob.exprs))] - [((~datum Expr) block:BlockClass) + [((~datum NT-Expr) block:BlockClass) (my-expand (syntax/loc stx block))] - [((~datum Expr) sexpr:SexprClass) + [((~datum NT-Expr) sexpr:SexprClass) (syntax/loc stx (read sexpr))])) ; struct-copy would not retain the sub-struct identity and fields, producing just a node @@ -1603,30 +1620,26 @@ #:track-literals [((~var macro-id id) . pattern) pattern-directive ... (syntax/loc stx template)]))))])) -(dsm-keep (Expr1 stx ...) (Expr stx ...)) -(dsm-keep (Expr1.5 stx ...) (Expr stx ...)) -(dsm-keep (Expr2 stx ...) (Expr stx ...)) -(dsm-keep (Expr3 stx ...) (Expr stx ...)) -(dsm-keep (Expr4 stx ...) (Expr stx ...)) -(dsm-keep (Expr4.5 stx ...) (Expr stx ...)) -(dsm-keep (Expr5 stx ...) (Expr stx ...)) -(dsm-keep (Expr6 stx ...) (Expr stx ...)) -(dsm-keep (Expr7 stx ...) (Expr stx ...)) -(dsm-keep (Expr7.5 stx ...) (Expr stx ...)) -(dsm-keep (Expr8 stx ...) (Expr stx ...)) -(dsm-keep (Expr9 stx ...) (Expr stx ...)) -(dsm-keep (Expr10 stx ...) (Expr stx ...)) -(dsm-keep (Expr11 stx ...) (Expr stx ...)) -(dsm-keep (Expr12 stx ...) (Expr stx ...)) -(dsm-keep (Expr13 stx ...) (Expr stx ...)) -(dsm-keep (Expr14 stx ...) (Expr stx ...)) -(dsm-keep (Expr15 stx ...) (Expr stx ...)) -(dsm-keep (Expr16 stx ...) (Expr stx ...)) -(dsm-keep (Expr17 stx ...) (Expr stx ...)) - - - - +(dsm-keep (NT-Expr1 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr1.5 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr2 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr3 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr4 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr4.5 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr5 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr6 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr7 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr7.5 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr8 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr9 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr10 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr11 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr12 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr13 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr14 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr15 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr16 stx ...) (NT-Expr stx ...)) +(dsm-keep (NT-Expr17 stx ...) (NT-Expr stx ...)) ; Transition System Stuff to be implemented ; StateDecl : STATE-TOK /LEFT-SQUARE-TOK QualName /RIGHT-SQUARE-TOK @@ -1652,7 +1665,7 @@ ; Helper(s) for debugging syntax class nesting ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-syntax (debug stx) +#;(define-syntax (debug stx) (define result (syntax-parse stx [(_ x:BoundsClass) (syntax/loc this-syntax x.translate)] diff --git a/forge/lang/reader.rkt b/forge/lang/reader.rkt index d084d522..eb8dc5de 100644 --- a/forge/lang/reader.rkt +++ b/forge/lang/reader.rkt @@ -27,8 +27,8 @@ (define (coerce-ints-to-atoms tree) ; AlloyModule: ModuleDecl? Import* Paragraph* - (syntax-parse tree #:datum-literals (AlloyModule ModuleDecl Import) - [(AlloyModule (~optional (~and module-decl + (syntax-parse tree #:datum-literals (NT-AlloyModule NT-ModuleDecl NT-Import) + [(NT-AlloyModule (~optional (~and module-decl (ModuleDecl _ ...))) (~seq (~and import (Import _ ...)) ...) @@ -39,7 +39,7 @@ ; (printf "Module-decl ~a~n~n" #'(~? module-decl "None present")) ; (printf "Paragraphs: ~a~n~n" #'(paragraphs ...)) (quasisyntax/loc tree - (AlloyModule (~? module-decl) + (NT-AlloyModule (~? module-decl) import ... paragraphs ...))])) @@ -48,8 +48,8 @@ (syntax-parse expr #:datum-literals (Name QualName Const Number) [(_ (Const (~optional "-") (Number n))) (quasisyntax/loc expr - (Expr - #,(quasisyntax/loc expr (Expr + (NT-Expr + #,(quasisyntax/loc expr (NT-Expr #,(quasisyntax/loc expr (QualName sing)))) "[" #,(quasisyntax/loc expr (ExprList #,expr)) "]"))] [(_ (~or (Name (~literal sing)) diff --git a/forge/server/forgeserver.rkt b/forge/server/forgeserver.rkt index ce16c8f6..569a746e 100644 --- a/forge/server/forgeserver.rkt +++ b/forge/server/forgeserver.rkt @@ -454,7 +454,9 @@ ; Read command as syntax from pipe (define expr (cond [(equal? (get-option curr-state 'eval-language) 'surface) - (forge-lang:parse "/no-name" (forge-lang:make-tokenizer pipe2))] + (let* ([tokenizer (forge-lang:make-tokenizer pipe2)] + [parsed (forge-lang:parse "/no-name-evaluator" tokenizer)]) + parsed)] [(equal? (get-option curr-state 'eval-language) 'core) (read-syntax 'Evaluator pipe1)] [else (raise-forge-error diff --git a/forge/solver-specific/translate-to-kodkod-cli.rkt b/forge/solver-specific/translate-to-kodkod-cli.rkt index 841450eb..9f7a6733 100644 --- a/forge/solver-specific/translate-to-kodkod-cli.rkt +++ b/forge/solver-specific/translate-to-kodkod-cli.rkt @@ -170,7 +170,9 @@ [(node/expr/relation info arity name typelist-thunk parent isvar) (print-cmd-cont (format-relname isvar name " "))] [(node/expr/atom info arity name) - (unless (member name atom-names) (raise (format "Atom ~a not in available atoms ~a" name atom-names))) + (unless (member name atom-names) + (raise-forge-error #:msg (format "Atom ~a not in available atoms ~a" name atom-names) + #:context info)) ( print-cmd-cont (format "~a " (a (index-of atom-names name))))] [(node/expr/fun-spacer info arity name args result expanded) (interpret-expr run-or-state expanded relations atom-names quantvars)] diff --git a/forge/tests/forge/other/empty.frg b/forge/tests/forge/other/empty.frg new file mode 100644 index 00000000..87a17b6f --- /dev/null +++ b/forge/tests/forge/other/empty.frg @@ -0,0 +1,3 @@ +#lang forge + +// Contains nothing \ No newline at end of file diff --git a/forge/tests/forge/other/internal-ids-preds.frg b/forge/tests/forge/other/internal-ids-preds.frg new file mode 100644 index 00000000..280ee6fe --- /dev/null +++ b/forge/tests/forge/other/internal-ids-preds.frg @@ -0,0 +1,128 @@ +#lang forge + +open "empty.frg" + +option run_sterling off +option verbose 0 + +/* + See internal-ids-sigs.frg for more information. This is a variant of that test file + that declares predicates rather than sigs. +*/ + +pred AlloyModule {} +pred Block {} +pred ModuleDecl {} +pred Import {} +pred SigDecl {} +pred RelDecl {} +pred PredDecl {} +pred FunDecl {} +pred CmdDecl {} +pred TestDecl {} +pred TestExpectDecl {} +pred PropertyDecl {} +pred QuantifiedPropertyDecl {} +pred SatisfiabilityDecl {} +pred ConsistencyDecl {} +pred TestSuiteDecl {} +pred ExampleDecl {} +pred Const {} +pred OptionDecl {} +pred InstDecl {} +pred Expr {} +pred Expr1 {} +pred Expr2 {} +pred Name {} +pred NameList {} +pred QualName {} +pred LetDecl {} +pred Bound {} +pred Scope {} +pred QualNameList {} +pred ParaDeclList {} +pred QuantDeclList {} +pred BlockOrBar {} +pred Quant {} +pred NumberList {} +pred Bounds {} +pred BoundLHS {} +pred BindRHSUnion {} +pred BindRHSProduct {} +pred BindRHSProductBase {} +pred AtomNameOrNumber {} +pred ArrowExpr {} +pred LetDeclList {} +pred TypescopeList {} +pred TestBlock {} +pred Paragraph {} +pred SigExt {} +pred Mult {} +pred ArrowMult {} +pred HelperMult {} +pred ParaDecl {} +pred QuantDecl {} +pred ArrowDecl {} +pred PredType {} +pred ParaDecls {} +pred TOMFParams {} +pred Typescope {} +pred TestConstruct {} +pred ArrowOp {} +pred CompareOp {} +pred Sexpr {} +pred Number {} + +// Used in evaluator queries about a specific instance +pred EvalDecl {} +// Not supported, but have a production anyway. Include to detect regressions. +pred AssertDecl {} +pred FactDecl {} + +// Trying various identifiers introduced by Forge and Racket +// helper macro defined by Forge, but not a keyword +pred ifte {} +// top-level AST struct name +pred node {} +// Racket-defined macros +pred lambda {} +// Racket-defined procedures +pred gensym {} +// Forge-defined helper procedures +pred primify {} +// Forge-defined struct +pred Sig {} +pred Run {} + +sig Node {edges: set Node, weightedEdges: set Node -> Int} + +pred foo {all n: Node | n = n} +fun bar: Int { let five = 5 | {x : Int | x = five} } +inst baz { Node = `Node0 + `Foo + no edges} +pred foo2[n1: Node, n2: Node] {} + +test suite for foo { + test expect { {foo} for baz is sat + {foo} for 3 Node is sat} +} +test expect { + {some Node} is sat + {some n: Node | foo2[n, n]} is sat + {some univ} is sat +} +assert {} is sat for {} +assert {} is sat for baz +assert {} is necessary for foo +assert {} is consistent with foo + +example anExample is {foo} for { + Node = `Node0 + `Node1 + `Providence + no `Node0.edges + `Node1.edges = `Providence +} + +exampleRun: run { + some Node => some Node else some Node + some (some Node => Node else Node) +} for exactly 5 Node diff --git a/forge/tests/forge/other/internal-ids-sigs.frg b/forge/tests/forge/other/internal-ids-sigs.frg new file mode 100644 index 00000000..7284e781 --- /dev/null +++ b/forge/tests/forge/other/internal-ids-sigs.frg @@ -0,0 +1,86 @@ +#lang forge + +open "empty.frg" + +option run_sterling off +option verbose 0 + +/* + Tests to ensure that internal expander-macro identifiers remain + inaccessible in the surface language. E.g., the "Block" macro has + been changed to the "NT-Block" (NT for non-terminal) macro, but + we want to confirm there are no regressions. + + It was also unnecessary to rename all non-terminals, and so some + of these serve an active purpose in verifying that it continues + to be unnecessary. +*/ + +sig AlloyModule, Block, ModuleDecl, Import, SigDecl, RelDecl + ,PredDecl, FunDecl, CmdDecl, TestDecl, TestExpectDecl + ,PropertyDecl,QuantifiedPropertyDecl, SatisfiabilityDecl + ,ConsistencyDecl, TestSuiteDecl, ExampleDecl, Const, OptionDecl + ,InstDecl, Expr, Expr1, Expr2, Name, NameList, QualName, LetDecl + ,Bound, Scope, QualNameList, ParaDeclList, QuantDeclList + ,BlockOrBar, Quant, NumberList, Bounds, BoundLHS, BindRHSUnion + ,BindRHSProduct, BindRHSProductBase, AtomNameOrNumber + ,ArrowExpr, LetDeclList, TypescopeList, TestBlock, Paragraph, SigExt + ,Mult, ArrowMult, HelperMult, ParaDecl, QuantDecl, ArrowDecl, PredType + ,ParaDecls, TOMFParams, Typescope, TestConstruct + ,ArrowOp, CompareOp, Sexpr, Number + + // Used in evaluator queries about a specific instance + , EvalDecl + + // Not supported, but have a production anyway. Include to detect regressions. + , AssertDecl ,FactDecl + + // Trying various identifiers introduced by Forge and Racket + + // helper macro defined by Forge, but not a keyword + ,ifte, debug + // top-level AST struct name + ,node + // Racket-defined macros + ,lambda + // Racket-defined procedures + ,gensym + // Forge-defined helper procedures + ,primify + // Forge-defined struct + ,Sig, Run + +{} + +sig Node {edges: set Node, weightedEdges: set Node -> Int} + +pred foo {all n: Node | n = n} +fun bar: Int { let five = 5 | {x : Int | x = five} } +inst baz { Node = `Node0 + `Foo + no edges} +pred foo2[n1: Node, n2: Node] {} + +test suite for foo { + test expect { {foo} for baz is sat + {foo} for 3 Node is sat} +} +test expect { + {some Node} is sat + {some n: Node | foo2[n, n]} is sat + {some univ} is sat +} +assert {} is sat for {} +assert {} is sat for baz +assert {} is necessary for foo +assert {} is consistent with foo + +example anExample is {foo} for { + Node = `Node0 + `Node1 + `Providence + no `Node0.edges + `Node1.edges = `Providence +} + +exampleRun: run { + some Node => some Node else some Node + some (some Node => Node else Node) +} for exactly 5 Node From 80a00857cb1258b821f3c2af9990d5a2069fab6a Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Sat, 14 Jun 2025 15:24:37 -0400 Subject: [PATCH 07/22] feat: chain of .ts/.js/.cnd files to Sterling --- forge/lang/alloy-syntax/parser.rkt | 4 +- forge/lang/expander.rkt | 21 +++++----- forge/server/modelToXML.rkt | 38 +++++++++++++------ forge/sigs-structs.rkt | 9 +++-- forge/sigs.rkt | 12 ++++-- forge/tests/forge/other/internal-ids-sigs.frg | 4 +- 6 files changed, 59 insertions(+), 29 deletions(-) diff --git a/forge/lang/alloy-syntax/parser.rkt b/forge/lang/alloy-syntax/parser.rkt index d03ea4b3..74a56039 100644 --- a/forge/lang/alloy-syntax/parser.rkt +++ b/forge/lang/alloy-syntax/parser.rkt @@ -134,7 +134,9 @@ NT-Block : /LEFT-CURLY-TOK NT-Expr* /RIGHT-CURLY-TOK BlockOrBar : NT-Block | BAR-TOK NT-Expr Quant : ALL-TOK | NO-TOK | SUM-TOK | @Mult QualName : (THIS-TOK /SLASH-TOK)? (@Name /SLASH-TOK)* @Name | INT-TOK | SUM-TOK -NT-OptionDecl : /OPTION-TOK QualName (QualName | PATH-OR-STR-TOK | MINUS-TOK? Number) + +; Some options now allow one-or-more paths. Specific details are validated later. +NT-OptionDecl : /OPTION-TOK QualName (QualName | PATH-OR-STR-TOK+ | MINUS-TOK? Number) Name : IDENTIFIER-TOK NameList : @Name diff --git a/forge/lang/expander.rkt b/forge/lang/expander.rkt index ac161507..d94144e5 100644 --- a/forge/lang/expander.rkt +++ b/forge/lang/expander.rkt @@ -485,18 +485,21 @@ (define-syntax-class OptionDeclClass #:attributes (n v) (pattern ((~datum NT-OptionDecl) name:QualNameClass value:QualNameClass) - #:attr n #'name.name - #:attr v #'value.name) + #:attr n #'name.name + #:attr v #'value.name) (pattern ((~datum NT-OptionDecl) name:QualNameClass value:str) - #:attr n #'name.name - #:attr v #'value) + #:attr n #'name.name + #:attr v #'value) + (pattern ((~datum NT-OptionDecl) name:QualNameClass (~seq values:str ...)) + #:attr n #'name.name + #:attr v #'(values ...)) (pattern ((~datum NT-OptionDecl) name:QualNameClass value:NumberClass) - #:attr n #'name.name - #:attr v #'value.value) + #:attr n #'name.name + #:attr v #'value.value) (pattern ((~datum NT-OptionDecl) name:QualNameClass "-" value:NumberClass) - #:attr n #'name.name - #:attr v (quasisyntax #,(* -1 (syntax->datum #'value.value))))) - + #:attr n #'name.name + #:attr v (quasisyntax #,(* -1 (syntax->datum #'value.value))))) + ; Block : /LEFT-CURLY-TOK Expr* /RIGHT-CURLY-TOK (define-syntax-class BlockClass diff --git a/forge/server/modelToXML.rkt b/forge/server/modelToXML.rkt index 8bf3bc27..6d08d5f6 100644 --- a/forge/server/modelToXML.rkt +++ b/forge/server/modelToXML.rkt @@ -3,6 +3,7 @@ (require forge/lang/ast racket/date xml racket/string forge/sigs-structs ; for Sat/Unsat forge/shared + racket/path (prefix-in @ (only-in racket > - +)) (only-in racket/port port->string) racket/hash @@ -81,20 +82,32 @@ (types-to-XML-string rel ID-hash) "\n\n\n")) -; Possibly annotate the XML with instructions on where to find visualization info +; Possibly annotate the XML with instructions on where to find visualization info. +; The option supports a _list_ of files, so Racket needs to disambiguate. (define (sterling-viz-to-xml run-options) + (define rs-opt (Options-run_sterling run-options)) + (define (single-path-to-xml p) + (cond [(and (string? p) (file-exists? p)) + ; the forge expander makes this an absolute path (see OptionDecl) + (define vis-text (port->string (open-input-file p) #:close? #t)) + (cond [(or (equal? (path-get-extension p) #".js") + (equal? (path-get-extension p) #".ts")) + (format " " (clean vis-text))] + [(equal? (path-get-extension p) #".cnd") + (format " " (clean vis-text))] + [else + (printf "A visualizer filename must end in either .js, .ts, or .cnd. Ignoring: ~a~n" p) + ""])] + [(string? p) + ; provided a path string, but there is no such file; show a warning but continue to load Sterling + (printf "A visualizer file in option run_sterling could not be found. Ignoring: ~a~n" p) + ""] + [else + ""])) (cond [(not run-options) ""] - [(and (string? (Options-run_sterling run-options)) - (file-exists? (Options-run_sterling run-options))) - ; the forge expander makes this an absolute path (see OptionDecl) - (define file-path (Options-run_sterling run-options)) - (define script-text (port->string (open-input-file file-path) #:close? #t)) - (format "" (clean script-text))] - [(string? (Options-run_sterling run-options)) - ; provided a path string, but there is no such file; show a warning but continue to load Sterling - (printf "The visualizer file in option run_sterling did not exist; ignoring: ~a~n" (Options-run_sterling run-options)) - ""] + [(string? rs-opt) (single-path-to-xml rs-opt)] + [(list? rs-opt) (apply string-append (map single-path-to-xml rs-opt))] [else ""])) (define (clean str) @@ -233,6 +246,7 @@ here-string-delimiter [else ; Sat! ; We have a LIST of instances in data + (define vis-xml (sterling-viz-to-xml run-options)) (define epilogue (string-append "\n" "lines (open-input-file filepath))))) "\">\n" - (sterling-viz-to-xml run-options) + vis-xml "")) (define message (string-append diff --git a/forge/sigs-structs.rkt b/forge/sigs-structs.rkt index 7c1c2cbb..80751a89 100644 --- a/forge/sigs-structs.rkt +++ b/forge/sigs-structs.rkt @@ -189,7 +189,7 @@ [core_minimization symbol?] [skolem_depth integer?] ; allow -1 (disable Skolemization entirely) [local_necessity symbol?] - [run_sterling (or/c string? symbol?)] + [run_sterling (or/c string? symbol? (listof string?))] [sterling_port nonnegative-integer?] [engine_verbosity nonnegative-integer?] [test_keep symbol?] @@ -312,7 +312,10 @@ 'core_minimization symbol? 'skolem_depth exact-integer? 'local_necessity symbol? - 'run_sterling (lambda (x) (or (symbol? x) (string? x))) ; allow for custom visualizer path + 'run_sterling (lambda (x) (or (symbol? x) + (string? x) + (and (list? x) + (andmap (lambda (ele) (string? ele)) x)))) 'sterling_port exact-nonnegative-integer? 'engine_verbosity exact-nonnegative-integer? 'test_keep (oneof-pred '(first last)) @@ -333,7 +336,7 @@ 'core_minimization "symbol" 'skolem_depth "integer" 'local_necessity "symbol" - 'run_sterling "symbol or string" + 'run_sterling "symbol, string, or sequence of strings" 'sterling_port "non-negative integer" 'engine_verbosity "non-negative integer" 'test_keep "one of: first or last" diff --git a/forge/sigs.rkt b/forge/sigs.rkt index c8615f70..b9b55c30 100644 --- a/forge/sigs.rkt +++ b/forge/sigs.rkt @@ -209,6 +209,9 @@ (unless ((hash-ref option-types option) value) (raise-user-error (format "Setting option ~a requires ~a; received ~a" option (hash-ref option-types-names option) value))) + + (define (translate-single-path p) + (path->string (build-path original-path (string->path p)))) (define new-options (cond @@ -268,9 +271,12 @@ [(equal? option 'run_sterling) (struct-copy Options options [run_sterling - (if (and (string? value) original-path) - (path->string (build-path original-path (string->path value))) - value)])] + (cond + [(and (string? value) original-path) + (translate-single-path value)] + [(and (list? value) original-path) + (map translate-single-path value)] + [else value])])] [(equal? option 'sterling_port) (struct-copy Options options [sterling_port value])] diff --git a/forge/tests/forge/other/internal-ids-sigs.frg b/forge/tests/forge/other/internal-ids-sigs.frg index 7284e781..d6ba563c 100644 --- a/forge/tests/forge/other/internal-ids-sigs.frg +++ b/forge/tests/forge/other/internal-ids-sigs.frg @@ -48,7 +48,9 @@ sig AlloyModule, Block, ModuleDecl, Import, SigDecl, RelDecl // Forge-defined helper procedures ,primify // Forge-defined struct - ,Sig, Run + ,Sig, Run, + // Syntax class definition + OptionDeclClass {} From 8edd9ad4efc91cc3ed8d5c8467e3671e77aa9428 Mon Sep 17 00:00:00 2001 From: Tim Nelson Date: Sat, 14 Jun 2025 16:28:43 -0400 Subject: [PATCH 08/22] update Sterling --- forge/sterling/README.md | 2 +- forge/sterling/build/6563.bundle.js | 2 +- forge/sterling/build/main.bundle.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/forge/sterling/README.md b/forge/sterling/README.md index cafa2cc0..02f4dec7 100644 --- a/forge/sterling/README.md +++ b/forge/sterling/README.md @@ -1,3 +1,3 @@ This folder contains a build of the current version of Sterling for Forge. To update, build Sterling and recursively copy the contents of the `dist` folder in that repo to the `build` sub-folder here. Remember to build with `yarn run build:forge`; the Forge version is slightly different from the Alloy version. - +Also, note well that the build has sub-folders. Don't neglect to `cp -r` and to delete the subfolders before copying. diff --git a/forge/sterling/build/6563.bundle.js b/forge/sterling/build/6563.bundle.js index 4083c070..e7c26a4b 100644 --- a/forge/sterling/build/6563.bundle.js +++ b/forge/sterling/build/6563.bundle.js @@ -1,2 +1,2 @@ /*! For license information please see 6563.bundle.js.LICENSE.txt */ -(self.webpackChunksterling_ts=self.webpackChunksterling_ts||[]).push([[6563],{68921:(e,t,n)=>{"use strict";n.d(t,{zx:()=>E,hE:()=>C,hU:()=>T});var i=n(97375),o=n(105),r=n(44592),s=n(38554),a=n.n(s),l=n(67294),c=n(26450),d=n(70917),u=n(1358);function h(){return h=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}(i,g),w=(0,r.cx)("chakra-spinner",b),C=h({display:"inline-block",borderColor:"currentColor",borderStyle:"solid",borderRadius:"99999px",borderWidth:d,borderBottomColor:_,borderLeftColor:_,animation:p+" "+m+" linear infinite"},n);return l.createElement(o.m$.div,h({ref:t,__css:C,className:w},y),a&&l.createElement(u.TX,null,a))}));function m(e,t){if(null==e)return{};var n,i,o={},r=Object.keys(e);for(i=0;i=0||(o[n]=e[n]);return o}function v(){return v=Object.assign||function(e){for(var t=1;t *:first-of-type:not(:last-of-type)":{borderEndRadius:0},"> *:not(:first-of-type):not(:last-of-type)":{borderRadius:0},"> *:not(:first-of-type):last-of-type":{borderStartRadius:0}}:{"& > *:not(style) ~ *:not(style)":{marginStart:d}}),l.createElement(y,{value:f},l.createElement(o.m$.div,v({ref:t,role:"group",__css:b,className:p},g)))}));r.Ts&&(C.displayName="ButtonGroup");var S=["label","placement","spacing","children","className","__css"],x=function(e){var t=e.label,n=e.placement;e.spacing;var i=e.children,s=void 0===i?l.createElement(f,{color:"currentColor",width:"1em",height:"1em"}):i,a=e.className,c=e.__css,d=m(e,S),u=(0,r.cx)("chakra-button__spinner",a),h="start"===n?"marginEnd":"marginStart",g=l.useMemo((function(){var e;return v(((e={display:"flex",alignItems:"center",position:t?"relative":"absolute"})[h]=t?"0.5rem":0,e.fontSize="1em",e.lineHeight="normal",e),c)}),[c,t,h]);return l.createElement(o.m$.div,v({className:u},d,{__css:g}),s)};r.Ts&&(x.displayName="ButtonSpinner");var k=["children","className"],L=function(e){var t=e.children,n=e.className,i=m(e,k),s=l.isValidElement(t)?l.cloneElement(t,{"aria-hidden":!0,focusable:!1}):t,a=(0,r.cx)("chakra-button__icon",n);return l.createElement(o.m$.span,v({display:"inline-flex",alignSelf:"center",flexShrink:0},i,{className:a}),s)};r.Ts&&(L.displayName="ButtonIcon");var N=["isDisabled","isLoading","isActive","isFullWidth","children","leftIcon","rightIcon","loadingText","iconSpacing","type","spinner","spinnerPlacement","className","as"],E=(0,o.Gp)((function(e,t){var n,s,c,d,u=w(),h=(0,o.mq)("Button",v({},u,e)),g=(0,o.Lr)(e),p=g.isDisabled,f=void 0===p?null==u?void 0:u.isDisabled:p,_=g.isLoading,b=g.isActive,y=g.isFullWidth,C=g.children,S=g.leftIcon,k=g.rightIcon,L=g.loadingText,E=g.iconSpacing,I=void 0===E?"0.5rem":E,T=g.type,M=g.spinner,A=g.spinnerPlacement,O=void 0===A?"start":A,R=g.className,P=g.as,F=m(g,N),B=l.useMemo((function(){var e,t=a()({},null!=(e=null==h?void 0:h._focus)?e:{},{zIndex:1});return v({display:"inline-flex",appearance:"none",alignItems:"center",justifyContent:"center",userSelect:"none",position:"relative",whiteSpace:"nowrap",verticalAlign:"middle",outline:"none",width:y?"100%":"auto"},h,!!u&&{_focus:t})}),[h,u,y]),W=(n=P,c=(s=l.useState(!n))[0],d=s[1],{ref:l.useCallback((function(e){e&&d("BUTTON"===e.tagName)}),[]),type:c?"button":void 0}),V=W.ref,z=W.type,H={rightIcon:k,leftIcon:S,iconSpacing:I,children:C};return l.createElement(o.m$.button,v({disabled:f||_,ref:(0,i.qq)(t,V),as:P,type:null!=T?T:z,"data-active":(0,r.PB)(b),"data-loading":(0,r.PB)(_),__css:B,className:(0,r.cx)("chakra-button",R)},F),_&&"start"===O&&l.createElement(x,{className:"chakra-button__spinner--start",label:L,placement:"start"},M),_?L||l.createElement(o.m$.span,{opacity:0},l.createElement(D,H)):l.createElement(D,H),_&&"end"===O&&l.createElement(x,{className:"chakra-button__spinner--end",label:L,placement:"end"},M))}));function D(e){var t=e.leftIcon,n=e.rightIcon,i=e.children,o=e.iconSpacing;return l.createElement(l.Fragment,null,t&&l.createElement(L,{marginEnd:o},t),i,n&&l.createElement(L,{marginStart:o},n))}r.Ts&&(E.displayName="Button");var I=["icon","children","isRound","aria-label"],T=(0,o.Gp)((function(e,t){var n=e.icon,i=e.children,o=e.isRound,r=e["aria-label"],s=m(e,I),a=n||i,c=l.isValidElement(a)?l.cloneElement(a,{"aria-hidden":!0,focusable:!1}):null;return l.createElement(E,v({padding:"0",borderRadius:o?"full":void 0,ref:t,"aria-label":r},s),c)}));r.Ts&&(T.displayName="IconButton")},68133:(e,t,n)=>{"use strict";n.d(t,{XZ:()=>L});var i=n(44592),o=n(26450),r=n(67294),s=n(97375),a=n(105),l=n(99860),c=n(53869),d=n(1358);function u(){return u=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}i.Ts;var f=["isIndeterminate","isChecked"],m="custom"in l.E?l.E.custom(a.m$.svg):(0,l.E)(a.m$.svg),v=function(e){return r.createElement(m,u({width:"1.2em",viewBox:"0 0 12 10",variants:{unchecked:{opacity:0,strokeDashoffset:16},checked:{opacity:1,strokeDashoffset:0,transition:{duration:.2}}},style:{fill:"none",strokeWidth:2,stroke:"currentColor",strokeDasharray:16}},e),r.createElement("polyline",{points:"1.5 6 4.5 9 10.5 1"}))},_=function(e){return r.createElement(m,u({width:"1.2em",viewBox:"0 0 24 24",variants:{unchecked:{scaleX:.65,opacity:0},checked:{scaleX:1,opacity:1,transition:{scaleX:{duration:0},opacity:{duration:.02}}}},style:{stroke:"currentColor",strokeWidth:4}},e),r.createElement("line",{x1:"21",x2:"3",y1:"12",y2:"12"}))},b=function(e){var t=e.open,n=e.children;return r.createElement(c.M,{initial:!1},t&&r.createElement(l.E.div,{variants:{unchecked:{scale:.5},checked:{scale:1}},initial:"unchecked",animate:"checked",exit:"unchecked",style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%"}},n))},y=function(e){var t=e.isIndeterminate,n=e.isChecked,i=p(e,f),o=t?_:v;return r.createElement(b,{open:n||t},r.createElement(o,i))},w=["defaultIsChecked","defaultChecked","isChecked","isFocusable","isDisabled","isReadOnly","isRequired","onChange","isIndeterminate","isInvalid","name","value","id","onBlur","onFocus","tabIndex","aria-label","aria-labelledby","aria-invalid","aria-describedby"];function C(e){e.preventDefault(),e.stopPropagation()}var S=["spacing","className","children","iconColor","iconSize","icon","isChecked","isDisabled","onChange"],x=(0,a.m$)("span",{baseStyle:{display:"inline-flex",alignItems:"center",justifyContent:"center",verticalAlign:"top",userSelect:"none",flexShrink:0}}),k=(0,a.m$)("label",{baseStyle:{cursor:"pointer",display:"inline-flex",alignItems:"center",verticalAlign:"top",position:"relative",_disabled:{cursor:"not-allowed"}}}),L=(0,a.Gp)((function(e,t){var n=g(),l=u({},n,e),c=(0,a.jC)("Checkbox",l),h=(0,a.Lr)(e),f=h.spacing,m=void 0===f?"0.5rem":f,v=h.className,_=h.children,b=h.iconColor,L=h.iconSize,N=h.icon,E=void 0===N?r.createElement(y,null):N,D=h.isChecked,I=h.isDisabled,T=void 0===I?null==n?void 0:n.isDisabled:I,M=h.onChange,A=p(h,S),O=D;null!=n&&n.value&&h.value&&(O=n.value.includes(h.value));var R=M;null!=n&&n.onChange&&h.value&&(R=(0,i.PP)(n.onChange,M));var P=function(e){void 0===e&&(e={});var t=e,n=t.defaultIsChecked,a=t.defaultChecked,l=void 0===a?n:a,c=t.isChecked,h=t.isFocusable,g=t.isDisabled,f=t.isReadOnly,m=t.isRequired,v=t.onChange,_=t.isIndeterminate,b=t.isInvalid,y=t.name,S=t.value,x=t.id,k=t.onBlur,L=t.onFocus,N=t.tabIndex,E=void 0===N?void 0:N,D=t["aria-label"],I=t["aria-labelledby"],T=t["aria-invalid"],M=t["aria-describedby"],A=p(t,w),O=(0,s.W6)(v),R=(0,s.W6)(k),P=(0,s.W6)(L),F=(0,s.kt)(),B=F[0],W=F[1],V=(0,s.kt)(),z=V[0],H=V[1],j=(0,s.kt)(),U=j[0],K=j[1],$=(0,r.useRef)(null),q=(0,r.useState)(!0),Z=q[0],G=q[1],Y=(0,r.useState)(!!l),Q=Y[0],X=Y[1],J=(0,s.pY)(c,Q),ee=J[0],te=J[1];(0,i.ZK)({condition:!!n,message:'The "defaultIsChecked" prop has been deprecated and will be removed in a future version. Please use the "defaultChecked" prop instead, which mirrors default React checkbox behavior.'});var ne=(0,r.useCallback)((function(e){f||g?e.preventDefault():(ee||X(te?e.target.checked:!!_||e.target.checked),null==O||O(e))}),[f,g,te,ee,_,O]);(0,s.Gw)((function(){$.current&&($.current.indeterminate=Boolean(_))}),[_]);var ie=g&&!h,oe=(0,r.useCallback)((function(e){" "===e.key&&K.on()}),[K]),re=(0,r.useCallback)((function(e){" "===e.key&&K.off()}),[K]);(0,s.Gw)((function(){$.current&&$.current.checked!==te&&X($.current.checked)}),[$.current]);var se=(0,r.useCallback)((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),u({},e,{ref:t,"data-active":(0,i.PB)(U),"data-hover":(0,i.PB)(z),"data-checked":(0,i.PB)(te),"data-focus":(0,i.PB)(B),"data-indeterminate":(0,i.PB)(_),"data-disabled":(0,i.PB)(g),"data-invalid":(0,i.PB)(b),"data-readonly":(0,i.PB)(f),"aria-hidden":!0,onMouseDown:(0,i.v0)(e.onMouseDown,(function(e){e.preventDefault(),K.on()})),onMouseUp:(0,i.v0)(e.onMouseUp,K.off),onMouseEnter:(0,i.v0)(e.onMouseEnter,H.on),onMouseLeave:(0,i.v0)(e.onMouseLeave,H.off)})}),[U,te,g,B,z,_,b,f,K,H.off,H.on]),ae=(0,r.useCallback)((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),u({},A,e,{ref:(0,o.lq)(t,(function(e){e&&G("LABEL"===e.tagName)})),onClick:(0,i.v0)(e.onClick,(function(){var e;Z||(null==(e=$.current)||e.click(),(0,i.T_)($.current,{nextTick:!0}))})),"data-disabled":(0,i.PB)(g),"data-checked":(0,i.PB)(te),"data-invalid":(0,i.PB)(b)})}),[A,g,te,b,Z]),le=(0,r.useCallback)((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),u({},e,{ref:(0,o.lq)($,t),type:"checkbox",name:y,value:S,id:x,tabIndex:E,onChange:(0,i.v0)(e.onChange,ne),onBlur:(0,i.v0)(e.onBlur,R,W.off),onFocus:(0,i.v0)(e.onFocus,P,W.on),onKeyDown:(0,i.v0)(e.onKeyDown,oe),onKeyUp:(0,i.v0)(e.onKeyUp,re),required:m,checked:te,disabled:ie,readOnly:f,"aria-label":D,"aria-labelledby":I,"aria-invalid":T?Boolean(T):b,"aria-describedby":M,"aria-disabled":g,style:d.NL})}),[y,S,x,ne,W.off,W.on,R,P,oe,re,m,te,ie,f,D,I,T,b,M,g,E]),ce=(0,r.useCallback)((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),u({},e,{ref:t,onMouseDown:(0,i.v0)(e.onMouseDown,C),onTouchStart:(0,i.v0)(e.onTouchStart,C),"data-disabled":(0,i.PB)(g),"data-checked":(0,i.PB)(te),"data-invalid":(0,i.PB)(b)})}),[te,g,b]);return{state:{isInvalid:b,isFocused:B,isChecked:te,isActive:U,isHovered:z,isIndeterminate:_,isDisabled:g,isReadOnly:f,isRequired:m},getRootProps:ae,getCheckboxProps:se,getInputProps:le,getLabelProps:ce,htmlProps:A}}(u({},A,{isDisabled:T,isChecked:O,onChange:R})),F=P.state,B=P.getInputProps,W=P.getCheckboxProps,V=P.getLabelProps,z=P.getRootProps,H=r.useMemo((function(){return u({opacity:F.isChecked||F.isIndeterminate?1:0,transform:F.isChecked||F.isIndeterminate?"scale(1)":"scale(0.95)",fontSize:L,color:b},c.icon)}),[b,L,F.isChecked,F.isIndeterminate,c.icon]),j=r.cloneElement(E,{__css:H,isIndeterminate:F.isIndeterminate,isChecked:F.isChecked});return r.createElement(k,u({__css:c.container,className:(0,i.cx)("chakra-checkbox",v)},z()),r.createElement("input",u({className:"chakra-checkbox__input"},B({},t))),r.createElement(x,u({__css:c.control,className:"chakra-checkbox__control"},W()),j),_&&r.createElement(a.m$.span,u({className:"chakra-checkbox__label"},V(),{__css:u({marginStart:m},c.label)}),_))}));i.Ts&&(L.displayName="Checkbox")},84746:(e,t,n)=>{"use strict";n.d(t,{P:()=>d});var i=n(10894),o=n(105),r=n(44592),s=n(67294);function a(){return a=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}(i,l);return s.createElement(o.m$.button,a({type:"button","aria-label":"Close",ref:t,disabled:d,__css:a({},{outline:0,display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0},n,u)},h),r||s.createElement(c,{width:"1em",height:"1em"}))}));r.Ts&&(d.displayName="CloseButton")},20949:(e,t,n)=>{"use strict";n.d(t,{kc:()=>f,SG:()=>v,If:()=>m});var i=n(85393),o=n(44592),r=n(67294),s="chakra-ui-light",a="chakra-ui-dark",l={classList:{add:o.ZT,remove:o.ZT}};var c="(prefers-color-scheme: dark)";var d=function(){return document.documentElement.style.getPropertyValue("--chakra-ui-color-mode")},u=function(e){o.jU&&document.documentElement.style.setProperty("--chakra-ui-color-mode",e)},h=function(){return"undefined"!=typeof Storage},g="chakra-ui-color-mode",p={get:function(e){if(!h())return e;try{var t=localStorage.getItem(g);return null!=t?t:e}catch(t){return o.Ts&&console.log(t),e}},set:function(e){if(h())try{localStorage.setItem(g,e)}catch(e){o.Ts&&console.log(e)}},type:"localStorage"},f=r.createContext({});o.Ts&&(f.displayName="ColorModeContext");var m=function(){var e=r.useContext(f);if(void 0===e)throw new Error("useColorMode must be used within a ColorModeProvider");return e};function v(e){var t=e.value,n=e.children,h=e.options,g=h.useSystemColorMode,m=h.initialColorMode,v=e.colorModeManager,_=void 0===v?p:v,b="dark"===m?"dark":"light",y=r.useState("cookie"===_.type?_.get(b):b),w=y[0],C=y[1],S=(0,i.O)().document;r.useEffect((function(){if(o.jU&&"localStorage"===_.type){var e=(i=b,(null!=(r=function(e){var t=null==window.matchMedia?void 0:window.matchMedia("(prefers-color-scheme: dark)");if(t)return!!t.media===t.matches}())?r:"dark"===i)?"dark":"light");if(g)return C(e);var t=d(),n=_.get();return C(t||(n||("system"===m?e:b)))}var i,r}),[_,g,b,m]),r.useEffect((function(){var e="dark"===w;(function(e,t){var n=function(e){return o.jU?e.body:l}(t);n.classList.add(e?a:s),n.classList.remove(e?s:a)})(e,S),u(e?"dark":"light")}),[w,S]);var x=r.useCallback((function(e,t){if(void 0===t&&(t=!1),t){if(_.get()&&!g)return}else _.set(e);C(e)}),[_,g]),k=r.useCallback((function(){x("light"===w?"dark":"light")}),[w,x]);r.useEffect((function(){var e,t=g||"system"===m;return t&&(e=function(e){if(!("matchMedia"in window))return o.ZT;var t=window.matchMedia(c),n=function(){e(t.matches?"dark":"light",!0)};return t.addEventListener("change",n),function(){t.removeEventListener("change",n)}}(x)),function(){e&&t&&e()}}),[x,g,m]);var L=r.useMemo((function(){return{colorMode:null!=t?t:w,toggleColorMode:t?o.ZT:k,setColorMode:t?o.ZT:x}}),[w,x,k,t]);return r.createElement(f.Provider,{value:L},n)}o.Ts&&(v.displayName="ColorModeProvider"),o.Ts,o.Ts},79762:(e,t,n)=>{"use strict";n.d(t,{NI:()=>m,lX:()=>k,Yp:()=>y,Kn:()=>w});var i=n(97375),o=n(105),r=n(44592),s=n(26450),a=n(67294),l=n(10894);function c(){return c=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}var u=["id","isRequired","isInvalid","isDisabled","isReadOnly"],h=["getRootProps","htmlProps"],g=(0,s.kr)({strict:!1,name:"FormControlContext"}),p=g[0],f=g[1],m=(0,o.Gp)((function(e,t){var n=(0,o.jC)("Form",e),l=function(e){var t=e.id,n=e.isRequired,o=e.isInvalid,l=e.isDisabled,h=e.isReadOnly,g=d(e,u),p=(0,i.Me)(),f=t||"field-"+p,m=f+"-label",v=f+"-feedback",_=f+"-helptext",b=a.useState(!1),y=b[0],w=b[1],C=a.useState(!1),S=C[0],x=C[1],k=(0,i.kt)(),L=k[0],N=k[1],E=a.useCallback((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),c({id:_},e,{ref:(0,s.lq)(t,(function(e){e&&x(!0)}))})}),[_]),D=a.useCallback((function(e,t){var n,i;return void 0===e&&(e={}),void 0===t&&(t=null),c({},e,{ref:t,"data-focus":(0,r.PB)(L),"data-disabled":(0,r.PB)(l),"data-invalid":(0,r.PB)(o),"data-readonly":(0,r.PB)(h),id:null!=(n=e.id)?n:m,htmlFor:null!=(i=e.htmlFor)?i:f})}),[f,l,L,o,h,m]),I=a.useCallback((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),c({id:v},e,{ref:(0,s.lq)(t,(function(e){e&&w(!0)})),"aria-live":"polite"})}),[v]),T=a.useCallback((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),c({},e,g,{ref:t,role:"group"})}),[g]),M=a.useCallback((function(e,t){return void 0===e&&(e={}),void 0===t&&(t=null),c({},e,{ref:t,role:"presentation","aria-hidden":!0,children:e.children||"*"})}),[]);return{isRequired:!!n,isInvalid:!!o,isReadOnly:!!h,isDisabled:!!l,isFocused:!!L,onFocus:N.on,onBlur:N.off,hasFeedbackText:y,setHasFeedbackText:w,hasHelpText:S,setHasHelpText:x,id:f,labelId:m,feedbackId:v,helpTextId:_,htmlProps:g,getHelpTextProps:E,getErrorMessageProps:I,getRootProps:T,getLabelProps:D,getRequiredIndicatorProps:M}}((0,o.Lr)(e)),g=l.getRootProps;l.htmlProps;var f=d(l,h),m=(0,r.cx)("chakra-form-control",e.className),v=a.useMemo((function(){return f}),[f]);return a.createElement(p,{value:v},a.createElement(o.Fo,{value:n},a.createElement(o.m$.div,c({},g({},t),{className:m,__css:n.container}))))}));r.Ts&&(m.displayName="FormControl");var v=(0,o.Gp)((function(e,t){var n=f(),i=(0,o.yK)(),s=(0,r.cx)("chakra-form__helper-text",e.className);return a.createElement(o.m$.div,c({},null==n?void 0:n.getHelpTextProps(e,t),{__css:i.helperText,className:s}))}));r.Ts&&(v.displayName="FormHelperText");var _=["isDisabled","isInvalid","isReadOnly","isRequired"],b=["id","disabled","readOnly","required","isRequired","isInvalid","isReadOnly","isDisabled","onFocus","onBlur"];function y(e){var t=w(e),n=t.isDisabled,i=t.isInvalid,o=t.isReadOnly,s=t.isRequired;return c({},d(t,_),{disabled:n,readOnly:o,required:s,"aria-invalid":(0,r.Qm)(i),"aria-required":(0,r.Qm)(s),"aria-readonly":(0,r.Qm)(o)})}function w(e){var t,n,i,o=f(),s=e.id,a=e.disabled,l=e.readOnly,u=e.required,h=e.isRequired,g=e.isInvalid,p=e.isReadOnly,m=e.isDisabled,v=e.onFocus,_=e.onBlur,y=d(e,b),w=e["aria-describedby"]?[e["aria-describedby"]]:[];return null!=o&&o.hasFeedbackText&&null!=o&&o.isInvalid&&w.push(o.feedbackId),null!=o&&o.hasHelpText&&w.push(o.helpTextId),c({},y,{"aria-describedby":w.join(" ")||void 0,id:null!=s?s:null==o?void 0:o.id,isDisabled:null!=(t=null!=a?a:m)?t:null==o?void 0:o.isDisabled,isReadOnly:null!=(n=null!=l?l:p)?n:null==o?void 0:o.isReadOnly,isRequired:null!=(i=null!=u?u:h)?i:null==o?void 0:o.isRequired,isInvalid:null!=g?g:null==o?void 0:o.isInvalid,onFocus:(0,r.v0)(null==o?void 0:o.onFocus,v),onBlur:(0,r.v0)(null==o?void 0:o.onBlur,_)})}var C=(0,o.Gp)((function(e,t){var n=(0,o.jC)("FormError",e),i=(0,o.Lr)(e),s=f();return null!=s&&s.isInvalid?a.createElement(o.Fo,{value:n},a.createElement(o.m$.div,c({},null==s?void 0:s.getErrorMessageProps(i,t),{className:(0,r.cx)("chakra-form__error-message",e.className),__css:c({display:"flex",alignItems:"center"},n.text)}))):null}));r.Ts&&(C.displayName="FormErrorMessage");var S=(0,o.Gp)((function(e,t){var n=(0,o.yK)(),i=f();if(null==i||!i.isInvalid)return null;var s=(0,r.cx)("chakra-form__error-icon",e.className);return a.createElement(l.ZP,c({ref:t,"aria-hidden":!0},e,{__css:n.icon,className:s}),a.createElement("path",{fill:"currentColor",d:"M11.983,0a12.206,12.206,0,0,0-8.51,3.653A11.8,11.8,0,0,0,0,12.207,11.779,11.779,0,0,0,11.8,24h.214A12.111,12.111,0,0,0,24,11.791h0A11.766,11.766,0,0,0,11.983,0ZM10.5,16.542a1.476,1.476,0,0,1,1.449-1.53h.027a1.527,1.527,0,0,1,1.523,1.47,1.475,1.475,0,0,1-1.449,1.53h-.027A1.529,1.529,0,0,1,10.5,16.542ZM11,12.5v-6a1,1,0,0,1,2,0v6a1,1,0,1,1-2,0Z"}))}));r.Ts&&(S.displayName="FormErrorIcon");var x=["className","children","requiredIndicator"],k=(0,o.Gp)((function(e,t){var n,i=(0,o.mq)("FormLabel",e),s=(0,o.Lr)(e);s.className;var l=s.children,u=s.requiredIndicator,h=void 0===u?a.createElement(L,null):u,g=d(s,x),p=f(),m=null!=(n=null==p?void 0:p.getLabelProps(g,t))?n:c({ref:t},g);return a.createElement(o.m$.label,c({},m,{className:(0,r.cx)("chakra-form__label",s.className),__css:c({display:"block",textAlign:"start"},i)}),l,null!=p&&p.isRequired?h:null)}));r.Ts&&(k.displayName="FormLabel");var L=(0,o.Gp)((function(e,t){var n=f(),i=(0,o.yK)();if(null==n||!n.isRequired)return null;var s=(0,r.cx)("chakra-form__required-indicator",e.className);return a.createElement(o.m$.span,c({},null==n?void 0:n.getRequiredIndicatorProps(e,t),{__css:i.requiredIndicator,className:s}))}));r.Ts&&(L.displayName="RequiredIndicator")},97375:(e,t,n)=>{"use strict";n.d(t,{vc:()=>g,kt:()=>r,W6:()=>a,pY:()=>l,Tx:()=>c,qY:()=>m,OR:()=>v,Ck:()=>b,NW:()=>w,Me:()=>p,ZS:()=>f,Yz:()=>C,qq:()=>x,O3:()=>k,Gw:()=>s,bx:()=>N,KS:()=>E,zq:()=>y,rf:()=>_});var i=n(67294),o=n(44592);function r(e){void 0===e&&(e=!1);var t=(0,i.useState)(e),n=t[0],o=t[1];return[n,{on:(0,i.useCallback)((function(){o(!0)}),[]),off:(0,i.useCallback)((function(){o(!1)}),[]),toggle:(0,i.useCallback)((function(){o((function(e){return!e}))}),[])}]}n(20640);var s=o.jU?i.useLayoutEffect:i.useEffect;function a(e,t){void 0===t&&(t=[]);var n=i.useRef(e);return s((function(){n.current=e})),i.useCallback((function(){for(var e=arguments.length,t=new Array(e),i=0;i1?t-1:0),o=1;o0)&&(!(i&&!(0,o.lZ)(i).body.contains(i))&&!(null!=(n=t.current)&&n.contains(i)))}function N(e){void 0===e&&(e={});var t=e,n=t.timeout,o=void 0===n?300:n,r=t.preventDefault,s=void 0===r?function(){return!0}:r,a=i.useState([]),l=a[0],c=a[1],d=i.useRef(),u=function(){d.current&&(clearTimeout(d.current),d.current=null)};return i.useEffect((function(){return u}),[]),function(e){return function(t){if("Backspace"===t.key){var n=[].concat(l);return n.pop(),void c(n)}if(function(e){var t=e.key;return 1===t.length||t.length>1&&/[^a-zA-Z0-9]/.test(t)}(t)){var i=l.concat(t.key);s(t)&&(t.preventDefault(),t.stopPropagation()),c(i),e(i.join("")),u(),d.current=setTimeout((function(){c([]),d.current=null}),o)}}}}function E(e,t){var n=a(e);i.useEffect((function(){var e;if(null!=t)return e=window.setTimeout((function(){n()}),t),function(){e&&window.clearTimeout(e)}}),[t,n])}},10894:(e,t,n)=>{"use strict";n.d(t,{JO:()=>c,IU:()=>u,ZP:()=>d});var i=n(105),o=n(44592),r=n(67294);function s(){return s=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,a),_={ref:t,focusable:g,className:(0,o.cx)("chakra-icon",f),__css:s({w:"1em",h:"1em",display:"inline-block",lineHeight:"1em",flexShrink:0,color:u},m)},b=null!=c?c:l.viewBox;if(n&&"string"!=typeof n)return r.createElement(i.m$.svg,s({as:n},_,v));var y=null!=p?p:l.path;return r.createElement(i.m$.svg,s({verticalAlign:"middle",viewBox:b},_,v),y)}));o.Ts&&(c.displayName="Icon");var d=c;function u(e){var t=e.viewBox,n=void 0===t?"0 0 24 24":t,a=e.d,l=e.path,d=e.displayName,u=e.defaultProps,h=void 0===u?{}:u,g=(0,i.Gp)((function(e,t){return r.createElement(c,s({ref:t,viewBox:n},h,e),null!=l?l:r.createElement("path",{fill:"currentColor",d:a}))}));return o.Ts&&(g.displayName=d),g}},59876:(e,t,n)=>{"use strict";n.d(t,{XC:()=>r});var i=n(10894),o=n(67294),r=((0,i.IU)({d:"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z",displayName:"CopyIcon"}),(0,i.IU)({d:"M23.384,21.619,16.855,15.09a9.284,9.284,0,1,0-1.768,1.768l6.529,6.529a1.266,1.266,0,0,0,1.768,0A1.251,1.251,0,0,0,23.384,21.619ZM2.75,9.5a6.75,6.75,0,1,1,6.75,6.75A6.758,6.758,0,0,1,2.75,9.5Z",displayName:"SearchIcon"}),(0,i.IU)({d:"M23.414,20.591l-4.645-4.645a10.256,10.256,0,1,0-2.828,2.829l4.645,4.644a2.025,2.025,0,0,0,2.828,0A2,2,0,0,0,23.414,20.591ZM10.25,3.005A7.25,7.25,0,1,1,3,10.255,7.258,7.258,0,0,1,10.25,3.005Z",displayName:"Search2Icon"}),(0,i.IU)({d:"M21.4,13.7C20.6,13.9,19.8,14,19,14c-5,0-9-4-9-9c0-0.8,0.1-1.6,0.3-2.4c0.1-0.3,0-0.7-0.3-1 c-0.3-0.3-0.6-0.4-1-0.3C4.3,2.7,1,7.1,1,12c0,6.1,4.9,11,11,11c4.9,0,9.3-3.3,10.6-8.1c0.1-0.3,0-0.7-0.3-1 C22.1,13.7,21.7,13.6,21.4,13.7z",displayName:"MoonIcon"}),(0,i.IU)({displayName:"SunIcon",path:o.createElement("g",{strokeLinejoin:"round",strokeLinecap:"round",strokeWidth:"2",fill:"none",stroke:"currentColor"},o.createElement("circle",{cx:"12",cy:"12",r:"5"}),o.createElement("path",{d:"M12 1v2"}),o.createElement("path",{d:"M12 21v2"}),o.createElement("path",{d:"M4.22 4.22l1.42 1.42"}),o.createElement("path",{d:"M18.36 18.36l1.42 1.42"}),o.createElement("path",{d:"M1 12h2"}),o.createElement("path",{d:"M21 12h2"}),o.createElement("path",{d:"M4.22 19.78l1.42-1.42"}),o.createElement("path",{d:"M18.36 5.64l1.42-1.42"}))}),(0,i.IU)({d:"M0,12a1.5,1.5,0,0,0,1.5,1.5h8.75a.25.25,0,0,1,.25.25V22.5a1.5,1.5,0,0,0,3,0V13.75a.25.25,0,0,1,.25-.25H22.5a1.5,1.5,0,0,0,0-3H13.75a.25.25,0,0,1-.25-.25V1.5a1.5,1.5,0,0,0-3,0v8.75a.25.25,0,0,1-.25.25H1.5A1.5,1.5,0,0,0,0,12Z",displayName:"AddIcon"}),(0,i.IU)({displayName:"SmallAddIcon",viewBox:"0 0 20 20",path:o.createElement("path",{fill:"currentColor",d:"M14 9h-3V6c0-.55-.45-1-1-1s-1 .45-1 1v3H6c-.55 0-1 .45-1 1s.45 1 1 1h3v3c0 .55.45 1 1 1s1-.45 1-1v-3h3c.55 0 1-.45 1-1s-.45-1-1-1z",fillRule:"evenodd"})}),(0,i.IU)({viewBox:"0 0 14 14",d:"M14,7.77 L14,6.17 L12.06,5.53 L11.61,4.44 L12.49,2.6 L11.36,1.47 L9.55,2.38 L8.46,1.93 L7.77,0.01 L6.17,0.01 L5.54,1.95 L4.43,2.4 L2.59,1.52 L1.46,2.65 L2.37,4.46 L1.92,5.55 L0,6.23 L0,7.82 L1.94,8.46 L2.39,9.55 L1.51,11.39 L2.64,12.52 L4.45,11.61 L5.54,12.06 L6.23,13.98 L7.82,13.98 L8.45,12.04 L9.56,11.59 L11.4,12.47 L12.53,11.34 L11.61,9.53 L12.08,8.44 L14,7.75 L14,7.77 Z M7,10 C5.34,10 4,8.66 4,7 C4,5.34 5.34,4 7,4 C8.66,4 10,5.34 10,7 C10,8.66 8.66,10 7,10 Z",displayName:"SettingsIcon"}),(0,i.IU)({displayName:"CheckCircleIcon",d:"M12,0A12,12,0,1,0,24,12,12.014,12.014,0,0,0,12,0Zm6.927,8.2-6.845,9.289a1.011,1.011,0,0,1-1.43.188L5.764,13.769a1,1,0,1,1,1.25-1.562l4.076,3.261,6.227-8.451A1,1,0,1,1,18.927,8.2Z"}),(0,i.IU)({d:"M19.5,9.5h-.75V6.75a6.75,6.75,0,0,0-13.5,0V9.5H4.5a2,2,0,0,0-2,2V22a2,2,0,0,0,2,2h15a2,2,0,0,0,2-2V11.5A2,2,0,0,0,19.5,9.5Zm-9.5,6a2,2,0,1,1,3,1.723V19.5a1,1,0,0,1-2,0V17.223A1.994,1.994,0,0,1,10,15.5ZM7.75,6.75a4.25,4.25,0,0,1,8.5,0V9a.5.5,0,0,1-.5.5H8.25a.5.5,0,0,1-.5-.5Z",displayName:"LockIcon"}),(0,i.IU)({d:"M19.5,9.5h-.75V6.75A6.751,6.751,0,0,0,5.533,4.811a1.25,1.25,0,1,0,2.395.717A4.251,4.251,0,0,1,16.25,6.75V9a.5.5,0,0,1-.5.5H4.5a2,2,0,0,0-2,2V22a2,2,0,0,0,2,2h15a2,2,0,0,0,2-2V11.5A2,2,0,0,0,19.5,9.5Zm-9.5,6a2,2,0,1,1,3,1.723V19.5a1,1,0,0,1-2,0V17.223A1.994,1.994,0,0,1,10,15.5Z",displayName:"UnlockIcon"}),(0,i.IU)({displayName:"ViewIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M23.432,10.524C20.787,7.614,16.4,4.538,12,4.6,7.6,4.537,3.213,7.615.568,10.524a2.211,2.211,0,0,0,0,2.948C3.182,16.351,7.507,19.4,11.839,19.4h.308c4.347,0,8.671-3.049,11.288-5.929A2.21,2.21,0,0,0,23.432,10.524ZM7.4,12A4.6,4.6,0,1,1,12,16.6,4.6,4.6,0,0,1,7.4,12Z"}),o.createElement("circle",{cx:"12",cy:"12",r:"2"}))}),(0,i.IU)({displayName:"ViewOffIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M23.2,10.549a20.954,20.954,0,0,0-4.3-3.6l4-3.995a1,1,0,1,0-1.414-1.414l-.018.018a.737.737,0,0,1-.173.291l-19.5,19.5c-.008.007-.018.009-.026.017a1,1,0,0,0,1.631,1.088l4.146-4.146a11.26,11.26,0,0,0,4.31.939h.3c4.256,0,8.489-2.984,11.051-5.8A2.171,2.171,0,0,0,23.2,10.549ZM16.313,13.27a4.581,4.581,0,0,1-3,3.028,4.3,4.3,0,0,1-3.1-.19.253.253,0,0,1-.068-.407l5.56-5.559a.252.252,0,0,1,.407.067A4.3,4.3,0,0,1,16.313,13.27Z"}),o.createElement("path",{d:"M7.615,13.4a.244.244,0,0,0,.061-.24A4.315,4.315,0,0,1,7.5,12,4.5,4.5,0,0,1,12,7.5a4.276,4.276,0,0,1,1.16.173.244.244,0,0,0,.24-.062l1.941-1.942a.254.254,0,0,0-.1-.421A10.413,10.413,0,0,0,12,4.75C7.7,4.692,3.4,7.7.813,10.549a2.15,2.15,0,0,0-.007,2.9,21.209,21.209,0,0,0,3.438,3.03.256.256,0,0,0,.326-.029Z"}))}),(0,i.IU)({d:"M11.2857,6.05714 L10.08571,4.85714 L7.85714,7.14786 L7.85714,1 L6.14286,1 L6.14286,7.14786 L3.91429,4.85714 L2.71429,6.05714 L7,10.42857 L11.2857,6.05714 Z M1,11.2857 L1,13 L13,13 L13,11.2857 L1,11.2857 Z",displayName:"DownloadIcon",viewBox:"0 0 14 14"}),(0,i.IU)({displayName:"DeleteIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M19.452 7.5H4.547a.5.5 0 00-.5.545l1.287 14.136A2 2 0 007.326 24h9.347a2 2 0 001.992-1.819L19.95 8.045a.5.5 0 00-.129-.382.5.5 0 00-.369-.163zm-9.2 13a.75.75 0 01-1.5 0v-9a.75.75 0 011.5 0zm5 0a.75.75 0 01-1.5 0v-9a.75.75 0 011.5 0zM22 4h-4.75a.25.25 0 01-.25-.25V2.5A2.5 2.5 0 0014.5 0h-5A2.5 2.5 0 007 2.5v1.25a.25.25 0 01-.25.25H2a1 1 0 000 2h20a1 1 0 000-2zM9 3.75V2.5a.5.5 0 01.5-.5h5a.5.5 0 01.5.5v1.25a.25.25 0 01-.25.25h-5.5A.25.25 0 019 3.75z"}))}),(0,i.IU)({displayName:"RepeatIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M10.319,4.936a7.239,7.239,0,0,1,7.1,2.252,1.25,1.25,0,1,0,1.872-1.657A9.737,9.737,0,0,0,9.743,2.5,10.269,10.269,0,0,0,2.378,9.61a.249.249,0,0,1-.271.178l-1.033-.13A.491.491,0,0,0,.6,9.877a.5.5,0,0,0-.019.526l2.476,4.342a.5.5,0,0,0,.373.248.43.43,0,0,0,.062,0,.5.5,0,0,0,.359-.152l3.477-3.593a.5.5,0,0,0-.3-.844L5.15,10.172a.25.25,0,0,1-.2-.333A7.7,7.7,0,0,1,10.319,4.936Z"}),o.createElement("path",{d:"M23.406,14.1a.5.5,0,0,0,.015-.526l-2.5-4.329A.5.5,0,0,0,20.546,9a.489.489,0,0,0-.421.151l-3.456,3.614a.5.5,0,0,0,.3.842l1.848.221a.249.249,0,0,1,.183.117.253.253,0,0,1,.023.216,7.688,7.688,0,0,1-5.369,4.9,7.243,7.243,0,0,1-7.1-2.253,1.25,1.25,0,1,0-1.872,1.656,9.74,9.74,0,0,0,9.549,3.03,10.261,10.261,0,0,0,7.369-7.12.251.251,0,0,1,.27-.179l1.058.127a.422.422,0,0,0,.06,0A.5.5,0,0,0,23.406,14.1Z"}))}),(0,i.IU)({displayName:"RepeatClockIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M12.965,6a1,1,0,0,0-1,1v5.5a1,1,0,0,0,1,1h5a1,1,0,0,0,0-2h-3.75a.25.25,0,0,1-.25-.25V7A1,1,0,0,0,12.965,6Z"}),o.createElement("path",{d:"M12.567,1.258A10.822,10.822,0,0,0,2.818,8.4a.25.25,0,0,1-.271.163L.858,8.309a.514.514,0,0,0-.485.213.5.5,0,0,0-.021.53l2.679,4.7a.5.5,0,0,0,.786.107l3.77-3.746a.5.5,0,0,0-.279-.85L5.593,9.007a.25.25,0,0,1-.192-.35,8.259,8.259,0,1,1,7.866,11.59,1.25,1.25,0,0,0,.045,2.5h.047a10.751,10.751,0,1,0-.792-21.487Z"}))}),(0,i.IU)({displayName:"EditIcon",path:o.createElement("g",{fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeWidth:"2"},o.createElement("path",{d:"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}),o.createElement("path",{d:"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"}))}),(0,i.IU)({d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z",displayName:"ChevronLeftIcon"}),(0,i.IU)({d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z",displayName:"ChevronRightIcon"}));(0,i.IU)({displayName:"ChevronDownIcon",d:"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"}),(0,i.IU)({d:"M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z",displayName:"ChevronUpIcon"}),(0,i.IU)({d:"M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z",displayName:"ArrowBackIcon"}),(0,i.IU)({d:"M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z",displayName:"ArrowForwardIcon"}),(0,i.IU)({d:"M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z",displayName:"ArrowUpIcon"}),(0,i.IU)({viewBox:"0 0 16 16",d:"M11.891 9.992a1 1 0 1 1 1.416 1.415l-4.3 4.3a1 1 0 0 1-1.414 0l-4.3-4.3A1 1 0 0 1 4.71 9.992l3.59 3.591 3.591-3.591zm0-3.984L8.3 2.417 4.709 6.008a1 1 0 0 1-1.416-1.415l4.3-4.3a1 1 0 0 1 1.414 0l4.3 4.3a1 1 0 1 1-1.416 1.415z",displayName:"ArrowUpDownIcon"}),(0,i.IU)({d:"M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z",displayName:"ArrowDownIcon"}),(0,i.IU)({displayName:"ExternalLinkIcon",path:o.createElement("g",{fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeWidth:"2"},o.createElement("path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"}),o.createElement("path",{d:"M15 3h6v6"}),o.createElement("path",{d:"M10 14L21 3"}))}),(0,i.IU)({displayName:"LinkIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M10.458,18.374,7.721,21.11a2.853,2.853,0,0,1-3.942,0l-.892-.891a2.787,2.787,0,0,1,0-3.941l5.8-5.8a2.789,2.789,0,0,1,3.942,0l.893.892A1,1,0,0,0,14.94,9.952l-.893-.892a4.791,4.791,0,0,0-6.771,0l-5.8,5.8a4.787,4.787,0,0,0,0,6.77l.892.891a4.785,4.785,0,0,0,6.771,0l2.736-2.735a1,1,0,1,0-1.414-1.415Z"}),o.createElement("path",{d:"M22.526,2.363l-.892-.892a4.8,4.8,0,0,0-6.77,0l-2.905,2.9a1,1,0,0,0,1.414,1.414l2.9-2.9a2.79,2.79,0,0,1,3.941,0l.893.893a2.786,2.786,0,0,1,0,3.942l-5.8,5.8a2.769,2.769,0,0,1-1.971.817h0a2.766,2.766,0,0,1-1.969-.816,1,1,0,1,0-1.415,1.412,4.751,4.751,0,0,0,3.384,1.4h0a4.752,4.752,0,0,0,3.385-1.4l5.8-5.8a4.786,4.786,0,0,0,0-6.771Z"}))}),(0,i.IU)({displayName:"PlusSquareIcon",path:o.createElement("g",{fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeWidth:"2"},o.createElement("rect",{height:"18",width:"18",rx:"2",ry:"2",x:"3",y:"3"}),o.createElement("path",{d:"M12 8v8"}),o.createElement("path",{d:"M8 12h8"}))}),(0,i.IU)({displayName:"CalendarIcon",viewBox:"0 0 14 14",d:"M10.8889,5.5 L3.11111,5.5 L3.11111,7.05556 L10.8889,7.05556 L10.8889,5.5 Z M12.4444,1.05556 L11.6667,1.05556 L11.6667,0 L10.1111,0 L10.1111,1.05556 L3.88889,1.05556 L3.88889,0 L2.33333,0 L2.33333,1.05556 L1.55556,1.05556 C0.692222,1.05556 0.00777777,1.75556 0.00777777,2.61111 L0,12.5 C0,13.3556 0.692222,14 1.55556,14 L12.4444,14 C13.3,14 14,13.3556 14,12.5 L14,2.61111 C14,1.75556 13.3,1.05556 12.4444,1.05556 Z M12.4444,12.5 L1.55556,12.5 L1.55556,3.94444 L12.4444,3.94444 L12.4444,12.5 Z M8.55556,8.61111 L3.11111,8.61111 L3.11111,10.1667 L8.55556,10.1667 L8.55556,8.61111 Z"}),(0,i.IU)({d:"M0.913134,0.920639 C1.49851,0.331726 2.29348,0 3.12342,0 L10.8766,0 C11.7065,0 12.5015,0.331725 13.0869,0.920639 C13.6721,1.50939 14,2.30689 14,3.13746 L14,8.12943 C13.9962,8.51443 13.9059,8.97125 13.7629,9.32852 C13.6128,9.683 13.3552,10.0709 13.0869,10.3462 C12.813,10.6163 12.4265,10.8761 12.0734,11.0274 C11.7172,11.1716 11.2607,11.263 10.8766,11.2669 L10.1234,11.2669 L10.1234,12.5676 L10.1209,12.5676 C10.1204,12.793 10.0633,13.0791 9.97807,13.262 C9.8627,13.466 9.61158,13.7198 9.40818,13.8382 L9.40824,13.8383 C9.4077,13.8386 9.40716,13.8388 9.40661,13.8391 C9.40621,13.8393 9.4058,13.8396 9.40539,13.8398 L9.40535,13.8397 C9.22958,13.9254 8.94505,13.9951 8.75059,14 L8.74789,14 C8.35724,13.9963 7.98473,13.8383 7.71035,13.5617 L5.39553,11.2669 L3.12342,11.2669 C2.29348,11.2669 1.49851,10.9352 0.913134,10.3462 C0.644826,10.0709 0.387187,9.683 0.23711,9.32852 C0.0941235,8.97125 0.00379528,8.51443 0,8.12943 L0,3.13746 C0,2.30689 0.327915,1.50939 0.913134,0.920639 Z M3.12342,1.59494 C2.71959,1.59494 2.33133,1.75628 2.04431,2.04503 C1.75713,2.33395 1.59494,2.72681 1.59494,3.13746 L1.59494,8.12943 C1.59114,8.35901 1.62114,8.51076 1.71193,8.72129 C1.79563,8.9346 1.88065,9.06264 2.04431,9.22185 C2.33133,9.5106 2.71959,9.67195 3.12342,9.67195 L5.72383,9.67195 C5.93413,9.67195 6.13592,9.75502 6.28527,9.90308 L8.52848,12.1269 L8.52848,10.4694 C8.52848,10.029 8.88552,9.67195 9.32595,9.67195 L10.8766,9.67195 C11.1034,9.67583 11.2517,9.64614 11.4599,9.55518 C11.6712,9.47132 11.7976,9.38635 11.9557,9.22185 C12.1193,9.06264 12.2044,8.9346 12.2881,8.72129 C12.3789,8.51076 12.4089,8.35901 12.4051,8.12943 L12.4051,3.13746 C12.4051,2.72681 12.2429,2.33394 11.9557,2.04503 C11.6687,1.75628 11.2804,1.59494 10.8766,1.59494 L3.12342,1.59494 Z",displayName:"ChatIcon",viewBox:"0 0 14 14"}),(0,i.IU)({displayName:"TimeIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M12,0A12,12,0,1,0,24,12,12.014,12.014,0,0,0,12,0Zm0,22A10,10,0,1,1,22,12,10.011,10.011,0,0,1,12,22Z"}),o.createElement("path",{d:"M17.134,15.81,12.5,11.561V6.5a1,1,0,0,0-2,0V12a1,1,0,0,0,.324.738l4.959,4.545a1.01,1.01,0,0,0,1.413-.061A1,1,0,0,0,17.134,15.81Z"}))}),(0,i.IU)({displayName:"ArrowRightIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M13.584,12a2.643,2.643,0,0,1-.775,1.875L3.268,23.416a1.768,1.768,0,0,1-2.5-2.5l8.739-8.739a.25.25,0,0,0,0-.354L.768,3.084a1.768,1.768,0,0,1,2.5-2.5l9.541,9.541A2.643,2.643,0,0,1,13.584,12Z"}),o.createElement("path",{d:"M23.75,12a2.643,2.643,0,0,1-.775,1.875l-9.541,9.541a1.768,1.768,0,0,1-2.5-2.5l8.739-8.739a.25.25,0,0,0,0-.354L10.934,3.084a1.768,1.768,0,0,1,2.5-2.5l9.541,9.541A2.643,2.643,0,0,1,23.75,12Z"}))}),(0,i.IU)({displayName:"ArrowLeftIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M10.416,12a2.643,2.643,0,0,1,.775-1.875L20.732.584a1.768,1.768,0,0,1,2.5,2.5l-8.739,8.739a.25.25,0,0,0,0,.354l8.739,8.739a1.768,1.768,0,0,1-2.5,2.5l-9.541-9.541A2.643,2.643,0,0,1,10.416,12Z"}),o.createElement("path",{d:"M.25,12a2.643,2.643,0,0,1,.775-1.875L10.566.584a1.768,1.768,0,0,1,2.5,2.5L4.327,11.823a.25.25,0,0,0,0,.354l8.739,8.739a1.768,1.768,0,0,1-2.5,2.5L1.025,13.875A2.643,2.643,0,0,1,.25,12Z"}))}),(0,i.IU)({displayName:"AtSignIcon",d:"M12,.5A11.634,11.634,0,0,0,.262,12,11.634,11.634,0,0,0,12,23.5a11.836,11.836,0,0,0,6.624-2,1.25,1.25,0,1,0-1.393-2.076A9.34,9.34,0,0,1,12,21a9.132,9.132,0,0,1-9.238-9A9.132,9.132,0,0,1,12,3a9.132,9.132,0,0,1,9.238,9v.891a1.943,1.943,0,0,1-3.884,0V12A5.355,5.355,0,1,0,12,17.261a5.376,5.376,0,0,0,3.861-1.634,4.438,4.438,0,0,0,7.877-2.736V12A11.634,11.634,0,0,0,12,.5Zm0,14.261A2.763,2.763,0,1,1,14.854,12,2.812,2.812,0,0,1,12,14.761Z"}),(0,i.IU)({displayName:"AttachmentIcon",d:"M21.843,3.455a6.961,6.961,0,0,0-9.846,0L1.619,13.832a5.128,5.128,0,0,0,7.252,7.252L17.3,12.653A3.293,3.293,0,1,0,12.646,8L7.457,13.184A1,1,0,1,0,8.871,14.6L14.06,9.409a1.294,1.294,0,0,1,1.829,1.83L7.457,19.67a3.128,3.128,0,0,1-4.424-4.424L13.411,4.869a4.962,4.962,0,1,1,7.018,7.018L12.646,19.67a1,1,0,1,0,1.414,1.414L21.843,13.3a6.96,6.96,0,0,0,0-9.846Z"}),(0,i.IU)({displayName:"UpDownIcon",viewBox:"-1 -1 9 11",d:"M 3.5 0L 3.98809 -0.569442L 3.5 -0.987808L 3.01191 -0.569442L 3.5 0ZM 3.5 9L 3.01191 9.56944L 3.5 9.98781L 3.98809 9.56944L 3.5 9ZM 0.488094 3.56944L 3.98809 0.569442L 3.01191 -0.569442L -0.488094 2.43056L 0.488094 3.56944ZM 3.01191 0.569442L 6.51191 3.56944L 7.48809 2.43056L 3.98809 -0.569442L 3.01191 0.569442ZM -0.488094 6.56944L 3.01191 9.56944L 3.98809 8.43056L 0.488094 5.43056L -0.488094 6.56944ZM 3.98809 9.56944L 7.48809 6.56944L 6.51191 5.43056L 3.01191 8.43056L 3.98809 9.56944Z"}),(0,i.IU)({d:"M23.555,8.729a1.505,1.505,0,0,0-1.406-.98H16.062a.5.5,0,0,1-.472-.334L13.405,1.222a1.5,1.5,0,0,0-2.81,0l-.005.016L8.41,7.415a.5.5,0,0,1-.471.334H1.85A1.5,1.5,0,0,0,.887,10.4l5.184,4.3a.5.5,0,0,1,.155.543L4.048,21.774a1.5,1.5,0,0,0,2.31,1.684l5.346-3.92a.5.5,0,0,1,.591,0l5.344,3.919a1.5,1.5,0,0,0,2.312-1.683l-2.178-6.535a.5.5,0,0,1,.155-.543l5.194-4.306A1.5,1.5,0,0,0,23.555,8.729Z",displayName:"StarIcon"}),(0,i.IU)({displayName:"EmailIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("path",{d:"M11.114,14.556a1.252,1.252,0,0,0,1.768,0L22.568,4.87a.5.5,0,0,0-.281-.849A1.966,1.966,0,0,0,22,4H2a1.966,1.966,0,0,0-.289.021.5.5,0,0,0-.281.849Z"}),o.createElement("path",{d:"M23.888,5.832a.182.182,0,0,0-.2.039l-6.2,6.2a.251.251,0,0,0,0,.354l5.043,5.043a.75.75,0,1,1-1.06,1.061l-5.043-5.043a.25.25,0,0,0-.354,0l-2.129,2.129a2.75,2.75,0,0,1-3.888,0L7.926,13.488a.251.251,0,0,0-.354,0L2.529,18.531a.75.75,0,0,1-1.06-1.061l5.043-5.043a.251.251,0,0,0,0-.354l-6.2-6.2a.18.18,0,0,0-.2-.039A.182.182,0,0,0,0,6V18a2,2,0,0,0,2,2H22a2,2,0,0,0,2-2V6A.181.181,0,0,0,23.888,5.832Z"}))}),(0,i.IU)({d:"M2.20731,0.0127209 C2.1105,-0.0066419 1.99432,-0.00664663 1.91687,0.032079 C0.871279,0.438698 0.212942,1.92964 0.0580392,2.95587 C-0.426031,6.28627 2.20731,9.17133 4.62766,11.0689 C6.77694,12.7534 10.9012,15.5223 13.3409,12.8503 C13.6507,12.5211 14.0186,12.037 13.9993,11.553 C13.9412,10.7397 13.186,10.1588 12.6051,9.71349 C12.1598,9.38432 11.2304,8.47427 10.6495,8.49363 C10.1267,8.51299 9.79754,9.05515 9.46837,9.38432 L8.88748,9.96521 C8.79067,10.062 7.55145,9.24878 7.41591,9.15197 C6.91248,8.8228 6.4284,8.45491 6.00242,8.04829 C5.57644,7.64167 5.18919,7.19632 4.86002,6.73161 C4.7632,6.59607 3.96933,5.41495 4.04678,5.31813 C4.04678,5.31813 4.72448,4.58234 4.91811,4.2919 C5.32473,3.67229 5.63453,3.18822 5.16982,2.45243 C4.99556,2.18135 4.78257,1.96836 4.55021,1.73601 C4.14359,1.34875 3.73698,0.942131 3.27227,0.612963 C3.02055,0.419335 2.59457,0.0708094 2.20731,0.0127209 Z",displayName:"PhoneIcon",viewBox:"0 0 14 14"}),(0,i.IU)({viewBox:"0 0 10 10",d:"M3,2 C2.44771525,2 2,1.55228475 2,1 C2,0.44771525 2.44771525,0 3,0 C3.55228475,0 4,0.44771525 4,1 C4,1.55228475 3.55228475,2 3,2 Z M3,6 C2.44771525,6 2,5.55228475 2,5 C2,4.44771525 2.44771525,4 3,4 C3.55228475,4 4,4.44771525 4,5 C4,5.55228475 3.55228475,6 3,6 Z M3,10 C2.44771525,10 2,9.55228475 2,9 C2,8.44771525 2.44771525,8 3,8 C3.55228475,8 4,8.44771525 4,9 C4,9.55228475 3.55228475,10 3,10 Z M7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 Z M7,6 C6.44771525,6 6,5.55228475 6,5 C6,4.44771525 6.44771525,4 7,4 C7.55228475,4 8,4.44771525 8,5 C8,5.55228475 7.55228475,6 7,6 Z M7,10 C6.44771525,10 6,9.55228475 6,9 C6,8.44771525 6.44771525,8 7,8 C7.55228475,8 8,8.44771525 8,9 C8,9.55228475 7.55228475,10 7,10 Z",displayName:"DragHandleIcon"}),(0,i.IU)({displayName:"SpinnerIcon",path:o.createElement(o.Fragment,null,o.createElement("defs",null,o.createElement("linearGradient",{x1:"28.154%",y1:"63.74%",x2:"74.629%",y2:"17.783%",id:"a"},o.createElement("stop",{stopColor:"currentColor",offset:"0%"}),o.createElement("stop",{stopColor:"#fff",stopOpacity:"0",offset:"100%"}))),o.createElement("g",{transform:"translate(2)",fill:"none"},o.createElement("circle",{stroke:"url(#a)",strokeWidth:"4",cx:"10",cy:"12",r:"10"}),o.createElement("path",{d:"M10 2C4.477 2 0 6.477 0 12",stroke:"currentColor",strokeWidth:"4"}),o.createElement("rect",{fill:"currentColor",x:"8",width:"4",height:"4",rx:"8"})))}),(0,i.IU)({displayName:"CloseIcon",d:"M.439,21.44a1.5,1.5,0,0,0,2.122,2.121L11.823,14.3a.25.25,0,0,1,.354,0l9.262,9.263a1.5,1.5,0,1,0,2.122-2.121L14.3,12.177a.25.25,0,0,1,0-.354l9.263-9.262A1.5,1.5,0,0,0,21.439.44L12.177,9.7a.25.25,0,0,1-.354,0L2.561.44A1.5,1.5,0,0,0,.439,2.561L9.7,11.823a.25.25,0,0,1,0,.354Z"}),(0,i.IU)({displayName:"SmallCloseIcon",viewBox:"0 0 16 16",path:o.createElement("path",{d:"M9.41 8l2.29-2.29c.19-.18.3-.43.3-.71a1.003 1.003 0 0 0-1.71-.71L8 6.59l-2.29-2.3a1.003 1.003 0 0 0-1.42 1.42L6.59 8 4.3 10.29c-.19.18-.3.43-.3.71a1.003 1.003 0 0 0 1.71.71L8 9.41l2.29 2.29c.18.19.43.3.71.3a1.003 1.003 0 0 0 .71-1.71L9.41 8z",fillRule:"evenodd",fill:"currentColor"})}),(0,i.IU)({d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z",displayName:"NotAllowedIcon"}),(0,i.IU)({d:"M21,5H3C2.621,5,2.275,5.214,2.105,5.553C1.937,5.892,1.973,6.297,2.2,6.6l9,12 c0.188,0.252,0.485,0.4,0.8,0.4s0.611-0.148,0.8-0.4l9-12c0.228-0.303,0.264-0.708,0.095-1.047C21.725,5.214,21.379,5,21,5z",displayName:"TriangleDownIcon"}),(0,i.IU)({d:"M12.8,5.4c-0.377-0.504-1.223-0.504-1.6,0l-9,12c-0.228,0.303-0.264,0.708-0.095,1.047 C2.275,18.786,2.621,19,3,19h18c0.379,0,0.725-0.214,0.895-0.553c0.169-0.339,0.133-0.744-0.095-1.047L12.8,5.4z",displayName:"TriangleUpIcon"}),(0,i.IU)({displayName:"InfoOutlineIcon",path:o.createElement("g",{fill:"currentColor",stroke:"currentColor",strokeLinecap:"square",strokeWidth:"2"},o.createElement("circle",{cx:"12",cy:"12",fill:"none",r:"11",stroke:"currentColor"}),o.createElement("line",{fill:"none",x1:"11.959",x2:"11.959",y1:"11",y2:"17"}),o.createElement("circle",{cx:"11.959",cy:"7",r:"1",stroke:"none"}))}),(0,i.IU)({displayName:"BellIcon",d:"M12 22c1.1 0 2-.9 2-2h-4c0 1.1.89 2 2 2zm6-6v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"}),(0,i.IU)({d:"M12,0A12,12,0,1,0,24,12,12.013,12.013,0,0,0,12,0Zm.25,5a1.5,1.5,0,1,1-1.5,1.5A1.5,1.5,0,0,1,12.25,5ZM14.5,18.5h-4a1,1,0,0,1,0-2h.75a.25.25,0,0,0,.25-.25v-4.5a.25.25,0,0,0-.25-.25H10.5a1,1,0,0,1,0-2h1a2,2,0,0,1,2,2v4.75a.25.25,0,0,0,.25.25h.75a1,1,0,1,1,0,2Z"}),(0,i.IU)({d:"M12,0A12,12,0,1,0,24,12,12.013,12.013,0,0,0,12,0Zm0,19a1.5,1.5,0,1,1,1.5-1.5A1.5,1.5,0,0,1,12,19Zm1.6-6.08a1,1,0,0,0-.6.917,1,1,0,1,1-2,0,3,3,0,0,1,1.8-2.75A2,2,0,1,0,10,9.255a1,1,0,1,1-2,0,4,4,0,1,1,5.6,3.666Z",displayName:"QuestionIcon"}),(0,i.IU)({displayName:"QuestionOutlineIcon",path:o.createElement("g",{stroke:"currentColor",strokeWidth:"1.5"},o.createElement("path",{strokeLinecap:"round",fill:"none",d:"M9,9a3,3,0,1,1,4,2.829,1.5,1.5,0,0,0-1,1.415V14.25"}),o.createElement("path",{fill:"none",strokeLinecap:"round",d:"M12,17.25a.375.375,0,1,0,.375.375A.375.375,0,0,0,12,17.25h0"}),o.createElement("circle",{fill:"none",strokeMiterlimit:"10",cx:"12",cy:"12",r:"11.25"}))}),(0,i.IU)({d:"M11.983,0a12.206,12.206,0,0,0-8.51,3.653A11.8,11.8,0,0,0,0,12.207,11.779,11.779,0,0,0,11.8,24h.214A12.111,12.111,0,0,0,24,11.791h0A11.766,11.766,0,0,0,11.983,0ZM10.5,16.542a1.476,1.476,0,0,1,1.449-1.53h.027a1.527,1.527,0,0,1,1.523,1.47,1.475,1.475,0,0,1-1.449,1.53h-.027A1.529,1.529,0,0,1,10.5,16.542ZM11,12.5v-6a1,1,0,0,1,2,0v6a1,1,0,1,1-2,0Z",displayName:"WarningIcon"}),(0,i.IU)({displayName:"WarningTwoIcon",d:"M23.119,20,13.772,2.15h0a2,2,0,0,0-3.543,0L.881,20a2,2,0,0,0,1.772,2.928H21.347A2,2,0,0,0,23.119,20ZM11,8.423a1,1,0,0,1,2,0v6a1,1,0,1,1-2,0Zm1.05,11.51h-.028a1.528,1.528,0,0,1-1.522-1.47,1.476,1.476,0,0,1,1.448-1.53h.028A1.527,1.527,0,0,1,13.5,18.4,1.475,1.475,0,0,1,12.05,19.933Z"}),(0,i.IU)({viewBox:"0 0 14 14",path:o.createElement("g",{fill:"currentColor"},o.createElement("polygon",{points:"5.5 11.9993304 14 3.49933039 12.5 2 5.5 8.99933039 1.5 4.9968652 0 6.49933039"}))}),(0,i.IU)({displayName:"MinusIcon",path:o.createElement("g",{fill:"currentColor"},o.createElement("rect",{height:"4",width:"20",x:"2",y:"10"}))}),(0,i.IU)({displayName:"HamburgerIcon",viewBox:"0 0 24 24",d:"M 3 5 A 1.0001 1.0001 0 1 0 3 7 L 21 7 A 1.0001 1.0001 0 1 0 21 5 L 3 5 z M 3 11 A 1.0001 1.0001 0 1 0 3 13 L 21 13 A 1.0001 1.0001 0 1 0 21 11 L 3 11 z M 3 17 A 1.0001 1.0001 0 1 0 3 19 L 21 19 A 1.0001 1.0001 0 1 0 21 17 L 3 17 z"})},4612:(e,t,n)=>{"use strict";n.d(t,{II:()=>c});var i=n(79762),o=n(105),r=n(44592),s=n(67294),a=n(26450);function l(){return l=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}r.Ts&&(c.displayName="Input"),c.id="Input";var u=["placement"],h={left:{marginEnd:"-1px",borderEndRadius:0,borderEndColor:"transparent"},right:{marginStart:"-1px",borderStartRadius:0,borderStartColor:"transparent"}},g=(0,o.m$)("div",{baseStyle:{flex:"0 0 auto",width:"auto",display:"flex",alignItems:"center",whiteSpace:"nowrap"}}),p=(0,o.Gp)((function(e,t){var n,i=e.placement,r=void 0===i?"left":i,a=d(e,u),c=null!=(n=h[r])?n:{},p=(0,o.yK)();return s.createElement(g,l({ref:t},a,{__css:l({},p.addon,c)}))}));r.Ts&&(p.displayName="InputAddon");var f=(0,o.Gp)((function(e,t){return s.createElement(p,l({ref:t,placement:"left"},e,{className:(0,r.cx)("chakra-input__left-addon",e.className)}))}));r.Ts&&(f.displayName="InputLeftAddon"),f.id="InputLeftAddon";var m=(0,o.Gp)((function(e,t){return s.createElement(p,l({ref:t,placement:"right"},e,{className:(0,r.cx)("chakra-input__right-addon",e.className)}))}));r.Ts&&(m.displayName="InputRightAddon"),m.id="InputRightAddon";var v=["children","className"],_=(0,o.Gp)((function(e,t){var n=(0,o.jC)("Input",e),i=(0,o.Lr)(e),c=i.children,u=i.className,h=d(i,v),g=(0,r.cx)("chakra-input__group",u),p={},f=(0,a.WR)(c),m=n.field;f.forEach((function(e){var t,i;n&&(m&&"InputLeftElement"===e.type.id&&(p.paddingStart=null!=(t=m.height)?t:m.h),m&&"InputRightElement"===e.type.id&&(p.paddingEnd=null!=(i=m.height)?i:m.h),"InputRightAddon"===e.type.id&&(p.borderEndRadius=0),"InputLeftAddon"===e.type.id&&(p.borderStartRadius=0))}));var _=f.map((function(t){var n,i,o={size:(null==(n=t.props)?void 0:n.size)||e.size,variant:(null==(i=t.props)?void 0:i.variant)||e.variant};return"Input"!==t.type.id?s.cloneElement(t,o):s.cloneElement(t,Object.assign(o,p,t.props))}));return s.createElement(o.m$.div,l({className:g,ref:t,__css:{width:"100%",display:"flex",position:"relative"}},h),s.createElement(o.Fo,{value:n},_))}));r.Ts&&(_.displayName="InputGroup");var b=["placement"],y=["className"],w=["className"],C=(0,o.m$)("div",{baseStyle:{display:"flex",alignItems:"center",justifyContent:"center",position:"absolute",top:"0",zIndex:2}}),S=(0,o.Gp)((function(e,t){var n,i,r,a=e.placement,c=void 0===a?"left":a,u=d(e,b),h=(0,o.yK)().field,g=((r={})["left"===c?"insetStart":"insetEnd"]="0",r.width=null!=(n=null==h?void 0:h.height)?n:null==h?void 0:h.h,r.height=null!=(i=null==h?void 0:h.height)?i:null==h?void 0:h.h,r.fontSize=null==h?void 0:h.fontSize,r);return s.createElement(C,l({ref:t,__css:g},u))}));S.id="InputElement",r.Ts&&(S.displayName="InputElement");var x=(0,o.Gp)((function(e,t){var n=e.className,i=d(e,y),o=(0,r.cx)("chakra-input__left-element",n);return s.createElement(S,l({ref:t,placement:"left",className:o},i))}));x.id="InputLeftElement",r.Ts&&(x.displayName="InputLeftElement");var k=(0,o.Gp)((function(e,t){var n=e.className,i=d(e,w),o=(0,r.cx)("chakra-input__right-element",n);return s.createElement(S,l({ref:t,placement:"right",className:o},i))}));k.id="InputRightElement",r.Ts&&(k.displayName="InputRightElement")},68527:(e,t,n)=>{"use strict";n.d(t,{xu:()=>v,M5:()=>y,iz:()=>N,kC:()=>D,rj:()=>T,X6:()=>A,LZ:()=>Z,xv:()=>ne});var i=n(105),o=n(94244),r=n(44592),s=n(67294),a=n(10894),l=n(26450);function c(){return c=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}var u=["ratio","children","className"],h=(0,i.Gp)((function(e,t){var n=e.ratio,o=void 0===n?4/3:n,a=e.children,l=e.className,h=d(e,u),g=s.Children.only(a),p=(0,r.cx)("chakra-aspect-ratio",l);return s.createElement(i.m$.div,c({ref:t,position:"relative",className:p,_before:{height:0,content:'""',display:"block",paddingBottom:(0,r.XQ)(o,(function(e){return 1/e*100+"%"}))},__css:{"& > *:not(style)":{overflow:"hidden",position:"absolute",top:"0",right:"0",bottom:"0",left:"0",display:"flex",justifyContent:"center",alignItems:"center",width:"100%",height:"100%"},"& > img, & > video":{objectFit:"cover"}}},h),g)}));r.Ts&&(h.displayName="AspectRatio");var g=["className"],p=(0,i.Gp)((function(e,t){var n=(0,i.mq)("Badge",e),o=(0,i.Lr)(e);o.className;var a=d(o,g);return s.createElement(i.m$.span,c({ref:t,className:(0,r.cx)("chakra-badge",e.className)},a,{__css:c({display:"inline-block",whiteSpace:"nowrap",verticalAlign:"middle"},n)}))}));r.Ts&&(p.displayName="Badge");var f=["size","centerContent"],m=["size"],v=(0,i.m$)("div");r.Ts&&(v.displayName="Box");var _=(0,i.Gp)((function(e,t){var n=e.size,i=e.centerContent,o=void 0===i||i,r=d(e,f),a=o?{display:"flex",alignItems:"center",justifyContent:"center"}:{};return s.createElement(v,c({ref:t,boxSize:n,__css:c({},a,{flexShrink:0,flexGrow:0})},r))}));r.Ts&&(_.displayName="Square");var b=(0,i.Gp)((function(e,t){var n=e.size,i=d(e,m);return s.createElement(_,c({size:n,ref:t,borderRadius:"9999px"},i))}));r.Ts&&(b.displayName="Circle");var y=(0,i.m$)("div",{baseStyle:{display:"flex",alignItems:"center",justifyContent:"center"}});r.Ts&&(y.displayName="Center");var w=["className"],C=(0,i.Gp)((function(e,t){var n=(0,i.mq)("Code",e),o=(0,i.Lr)(e);o.className;var a=d(o,w);return s.createElement(i.m$.code,c({ref:t,className:(0,r.cx)("chakra-code",e.className)},a,{__css:c({display:"inline-block"},n)}))}));r.Ts&&(C.displayName="Code");var S=["className","centerContent"],x=(0,i.Gp)((function(e,t){var n=(0,i.Lr)(e),o=n.className,a=n.centerContent,l=d(n,S),u=(0,i.mq)("Container",e);return s.createElement(i.m$.div,c({ref:t,className:(0,r.cx)("chakra-container",o)},l,{__css:c({},u,a&&{display:"flex",flexDirection:"column",alignItems:"center"})}))}));r.Ts&&(x.displayName="Container");var k=["borderLeftWidth","borderBottomWidth","borderTopWidth","borderRightWidth","borderWidth","borderStyle","borderColor"],L=["className","orientation","__css"],N=(0,i.Gp)((function(e,t){var n=(0,i.mq)("Divider",e),o=n.borderLeftWidth,a=n.borderBottomWidth,l=n.borderTopWidth,u=n.borderRightWidth,h=n.borderWidth,g=n.borderStyle,p=n.borderColor,f=d(n,k),m=(0,i.Lr)(e),v=m.className,_=m.orientation,b=void 0===_?"horizontal":_,y=m.__css,w=d(m,L),C={vertical:{borderLeftWidth:o||u||h||"1px",height:"100%"},horizontal:{borderBottomWidth:a||l||h||"1px",width:"100%"}};return s.createElement(i.m$.hr,c({ref:t,"aria-orientation":b},w,{__css:c({},f,{border:"0",borderColor:p,borderStyle:g},C[b],y),className:(0,r.cx)("chakra-divider",v)}))}));r.Ts&&(N.displayName="Divider");var E=["direction","align","justify","wrap","basis","grow","shrink"],D=(0,i.Gp)((function(e,t){var n=e.direction,o=e.align,r=e.justify,a=e.wrap,l=e.basis,u=e.grow,h=e.shrink,g=d(e,E),p={display:"flex",flexDirection:n,alignItems:o,justifyContent:r,flexWrap:a,flexBasis:l,flexGrow:u,flexShrink:h};return s.createElement(i.m$.div,c({ref:t,__css:p},g))}));r.Ts&&(D.displayName="Flex");var I=["area","templateAreas","gap","rowGap","columnGap","column","row","autoFlow","autoRows","templateRows","autoColumns","templateColumns"],T=(0,i.Gp)((function(e,t){var n=e.area,o=e.templateAreas,r=e.gap,a=e.rowGap,l=e.columnGap,u=e.column,h=e.row,g=e.autoFlow,p=e.autoRows,f=e.templateRows,m=e.autoColumns,v=e.templateColumns,_=d(e,I),b={display:"grid",gridArea:n,gridTemplateAreas:o,gridGap:r,gridRowGap:a,gridColumnGap:l,gridAutoColumns:m,gridColumn:u,gridRow:h,gridAutoFlow:g,gridAutoRows:p,gridTemplateRows:f,gridTemplateColumns:v};return s.createElement(i.m$.div,c({ref:t,__css:b},_))}));r.Ts&&(T.displayName="Grid");var M=["className"],A=(0,i.Gp)((function(e,t){var n=(0,i.mq)("Heading",e),o=(0,i.Lr)(e);o.className;var a=d(o,M);return s.createElement(i.m$.h2,c({ref:t,className:(0,r.cx)("chakra-heading",e.className)},a,{__css:n}))}));r.Ts&&(A.displayName="Heading");var O=["className"],R=(0,i.Gp)((function(e,t){var n=(0,i.mq)("Kbd",e),o=(0,i.Lr)(e),a=o.className,l=d(o,O);return s.createElement(i.m$.kbd,c({ref:t,className:(0,r.cx)("chakra-kbd",a)},l,{__css:c({fontFamily:"mono"},n)}))}));r.Ts&&(R.displayName="Kbd");var P=["className","isExternal"],F=(0,i.Gp)((function(e,t){var n=(0,i.mq)("Link",e),o=(0,i.Lr)(e),a=o.className,l=o.isExternal,u=d(o,P);return s.createElement(i.m$.a,c({target:l?"_blank":void 0,rel:l?"noopener noreferrer":void 0,ref:t,className:(0,r.cx)("chakra-link",a)},u,{__css:n}))}));r.Ts&&(F.displayName="Link");var B=["children","styleType","stylePosition","spacing"],W=["as"],V=["as"],z=(0,i.Gp)((function(e,t){var n,o=(0,i.jC)("List",e),r=(0,i.Lr)(e),a=r.children,u=r.styleType,h=void 0===u?"none":u,g=r.stylePosition,p=r.spacing,f=d(r,B),m=(0,l.WR)(a),v=p?((n={})["& > *:not(style) ~ *:not(style)"]={mt:p},n):{};return s.createElement(i.Fo,{value:o},s.createElement(i.m$.ul,c({ref:t,listStyleType:h,listStylePosition:g,role:"list",__css:c({},o.container,v)},f),m))}));r.Ts&&(z.displayName="List");var H=(0,i.Gp)((function(e,t){e.as;var n=d(e,W);return s.createElement(z,c({ref:t,as:"ol",styleType:"decimal",marginStart:"1em"},n))}));r.Ts&&(H.displayName="OrderedList");var j=(0,i.Gp)((function(e,t){e.as;var n=d(e,V);return s.createElement(z,c({ref:t,as:"ul",styleType:"initial",marginStart:"1em"},n))}));r.Ts&&(j.displayName="UnorderedList");var U=(0,i.Gp)((function(e,t){var n=(0,i.yK)();return s.createElement(i.m$.li,c({ref:t},e,{__css:n.item}))}));r.Ts&&(U.displayName="ListItem");var K=(0,i.Gp)((function(e,t){var n=(0,i.yK)();return s.createElement(a.JO,c({ref:t,role:"presentation"},e,{__css:n.icon}))}));r.Ts&&(K.displayName="ListIcon");var $=["columns","spacingX","spacingY","spacing","minChildWidth"],q=(0,i.Gp)((function(e,t){var n,i,o=e.columns,a=e.spacingX,l=e.spacingY,u=e.spacing,h=e.minChildWidth,g=d(e,$),p=h?(i=h,(0,r.XQ)(i,(function(e){return(0,r.Ft)(e)?null:"repeat(auto-fit, minmax("+(t=e,((0,r.hj)(t)?t+"px":t)+", 1fr))");var t}))):(n=o,(0,r.XQ)(n,(function(e){return(0,r.Ft)(e)?null:"repeat("+e+", minmax(0, 1fr))"})));return s.createElement(T,c({ref:t,gap:u,columnGap:a,rowGap:l,templateColumns:p},g))}));r.Ts&&(q.displayName="SimpleGrid");var Z=(0,i.m$)("div",{baseStyle:{flex:1,justifySelf:"stretch",alignSelf:"stretch"}});r.Ts&&(Z.displayName="Spacer");var G="& > *:not(style) ~ *:not(style)",Y=["isInline","direction","align","justify","spacing","wrap","children","divider","className","shouldWrapChildren"],Q=function(e){return s.createElement(i.m$.div,c({className:"chakra-stack__item"},e,{__css:c({display:"inline-block",flex:"0 0 auto",minWidth:0},e.__css)}))},X=(0,i.Gp)((function(e,t){var n,o=e.isInline,a=e.direction,u=e.align,h=e.justify,g=e.spacing,p=void 0===g?"0.5rem":g,f=e.wrap,m=e.children,v=e.divider,_=e.className,b=e.shouldWrapChildren,y=d(e,Y),w=o?"row":null!=a?a:"column",C=s.useMemo((function(){return function(e){var t,n=e.spacing,i=e.direction,o={column:{marginTop:n,marginEnd:0,marginBottom:0,marginStart:0},row:{marginTop:0,marginEnd:0,marginBottom:0,marginStart:n},"column-reverse":{marginTop:0,marginEnd:0,marginBottom:n,marginStart:0},"row-reverse":{marginTop:0,marginEnd:n,marginBottom:0,marginStart:0}};return(t={flexDirection:i})[G]=(0,r.XQ)(i,(function(e){return o[e]})),t}({direction:w,spacing:p})}),[w,p]),S=s.useMemo((function(){return function(e){var t=e.spacing,n=e.direction,i={column:{my:t,mx:0,borderLeftWidth:0,borderBottomWidth:"1px"},"column-reverse":{my:t,mx:0,borderLeftWidth:0,borderBottomWidth:"1px"},row:{mx:t,my:0,borderLeftWidth:"1px",borderBottomWidth:0},"row-reverse":{mx:t,my:0,borderLeftWidth:"1px",borderBottomWidth:0}};return{"&":(0,r.XQ)(n,(function(e){return i[e]}))}}({spacing:p,direction:w})}),[p,w]),x=!!v,k=!b&&!x,L=(0,l.WR)(m),N=k?L:L.map((function(e,t){var n=void 0!==e.key?e.key:t,i=t+1===L.length,o=b?s.createElement(Q,{key:n},e):e;if(!x)return o;var r=i?null:s.cloneElement(v,{__css:S});return s.createElement(s.Fragment,{key:n},o,r)})),E=(0,r.cx)("chakra-stack",_);return s.createElement(i.m$.div,c({ref:t,display:"flex",alignItems:u,justifyContent:h,flexDirection:C.flexDirection,flexWrap:f,className:E,__css:x?{}:(n={},n[G]=C[G],n)},y),N)}));r.Ts&&(X.displayName="Stack");var J=(0,i.Gp)((function(e,t){return s.createElement(X,c({align:"center"},e,{direction:"row",ref:t}))}));r.Ts&&(J.displayName="HStack");var ee=(0,i.Gp)((function(e,t){return s.createElement(X,c({align:"center"},e,{direction:"column",ref:t}))}));r.Ts&&(ee.displayName="VStack");var te=["className","align","decoration","casing"],ne=(0,i.Gp)((function(e,t){var n=(0,i.mq)("Text",e),o=(0,i.Lr)(e);o.className,o.align,o.decoration,o.casing;var a=d(o,te),l=(0,r.YU)({textAlign:e.align,textDecoration:e.decoration,textTransform:e.casing});return s.createElement(i.m$.p,c({ref:t,className:(0,r.cx)("chakra-text",e.className)},l,a,{__css:n}))}));r.Ts&&(ne.displayName="Text");var ie=["spacing","children","justify","direction","align","className","shouldWrapChildren"],oe=["className"],re=(0,i.Gp)((function(e,t){var n=e.spacing,a=void 0===n?"0.5rem":n,l=e.children,u=e.justify,h=e.direction,g=e.align,p=e.className,f=e.shouldWrapChildren,m=d(e,ie),v=s.useMemo((function(){return{"--chakra-wrap-spacing":function(e){return(0,r.XQ)(a,(function(t){return(0,o.fr)("space",t)(e)}))},"--wrap-spacing":"calc(var(--chakra-wrap-spacing) / 2)",display:"flex",flexWrap:"wrap",justifyContent:u,alignItems:g,flexDirection:h,listStyleType:"none",padding:"0",margin:"calc(var(--wrap-spacing) * -1)","& > *:not(style)":{margin:"var(--wrap-spacing)"}}}),[a,u,g,h]),_=f?s.Children.map(l,(function(e,t){return s.createElement(se,{key:t},e)})):l;return s.createElement(i.m$.div,c({ref:t,className:(0,r.cx)("chakra-wrap",p)},m),s.createElement(i.m$.ul,{className:"chakra-wrap__list",__css:v},_))}));r.Ts&&(re.displayName="Wrap");var se=(0,i.Gp)((function(e,t){var n=e.className,o=d(e,oe);return s.createElement(i.m$.li,c({ref:t,__css:{display:"flex",alignItems:"flex-start"},className:(0,r.cx)("chakra-wrap__listitem",n)},o))}));r.Ts&&(se.displayName="WrapItem")},47016:(e,t,n)=>{"use strict";n.d(t,{v2:()=>K,j2:()=>q,sN:()=>X,qy:()=>Y});var i=n(105),o=n(44592),r=n(99860),s=n(67294),a=n(26450);function l(){return l=Object.assign||function(e){for(var t=1;t=t&&(i=0),i}function p(e,t,n){var i=e-1;return n&&i<0&&(i=t),i}var f="undefined"!=typeof window?s.useLayoutEffect:s.useEffect,m=function(){var e=this;this.descendants=new Map,this.register=function(t){var n;if(null!=t)return"object"==typeof(n=t)&&"nodeType"in n&&n.nodeType===Node.ELEMENT_NODE?e.registerNode(t):function(n){e.registerNode(n,t)}},this.unregister=function(t){e.descendants.delete(t);var n=h(Array.from(e.descendants.keys()));e.assignIndex(n)},this.destroy=function(){e.descendants.clear()},this.assignIndex=function(t){e.descendants.forEach((function(e){var n=t.indexOf(e.node);e.index=n,e.node.dataset.index=e.index.toString()}))},this.count=function(){return e.descendants.size},this.enabledCount=function(){return e.enabledValues().length},this.values=function(){return Array.from(e.descendants.values()).sort((function(e,t){return e.index-t.index}))},this.enabledValues=function(){return e.values().filter((function(e){return!e.disabled}))},this.item=function(t){if(0!==e.count())return e.values()[t]},this.enabledItem=function(t){if(0!==e.enabledCount())return e.enabledValues()[t]},this.first=function(){return e.item(0)},this.firstEnabled=function(){return e.enabledItem(0)},this.last=function(){return e.item(e.descendants.size-1)},this.lastEnabled=function(){var t=e.enabledValues().length-1;return e.enabledItem(t)},this.indexOf=function(t){var n,i;return t&&null!=(n=null==(i=e.descendants.get(t))?void 0:i.index)?n:-1},this.enabledIndexOf=function(t){return null==t?-1:e.enabledValues().findIndex((function(e){return e.node.isSameNode(t)}))},this.next=function(t,n){void 0===n&&(n=!0);var i=g(t,e.count(),n);return e.item(i)},this.nextEnabled=function(t,n){void 0===n&&(n=!0);var i=e.item(t);if(i){var o=g(e.enabledIndexOf(i.node),e.enabledCount(),n);return e.enabledItem(o)}},this.prev=function(t,n){void 0===n&&(n=!0);var i=p(t,e.count()-1,n);return e.item(i)},this.prevEnabled=function(t,n){void 0===n&&(n=!0);var i=e.item(t);if(i){var o=p(e.enabledIndexOf(i.node),e.enabledCount()-1,n);return e.enabledItem(o)}},this.registerNode=function(t,n){if(t&&!e.descendants.has(t)){var i=h(Array.from(e.descendants.keys()).concat(t));null!=n&&n.disabled&&(n.disabled=!!n.disabled);var o=u({node:t,index:-1},n);e.descendants.set(t,o),e.assignIndex(i)}}},v=(0,a.kr)({name:"DescendantsProvider",errorMessage:"useDescendantsContext must be used within DescendantsProvider"}),_=v[0],b=v[1],y=n(97375),w=n(66197);function C(){return C=Object.assign||function(e){for(var t=1;t=0||(o[n]=e[n]);return o}var x=["id","closeOnSelect","closeOnBlur","autoSelect","isLazy","isOpen","defaultIsOpen","onClose","onOpen","placement","lazyBehavior","direction","computePositionOnMount"],k=["onMouseEnter","onMouseMove","onMouseLeave","onClick","isDisabled","isFocusable","closeOnSelect"],L=["type","isChecked"],N=[_,function(){return b()},function(){return e=(0,s.useRef)(new m),f((function(){return function(){return e.current.destroy()}})),e.current;var e},function(e){return function(e){var t=b(),n=(0,s.useState)(-1),i=n[0],o=n[1],r=(0,s.useRef)(null);f((function(){return function(){r.current&&t.unregister(r.current)}}),[]),f((function(){if(r.current){var e=Number(r.current.dataset.index);i==e||Number.isNaN(e)||o(e)}}));var l=e?t.register(e):t.register;return{descendants:t,index:i,enabledIndex:t.enabledIndexOf(r.current),register:(0,a.lq)(l,r)}}(e)}],E=N[0],D=N[1],I=N[2],T=N[3],M=(0,a.kr)({strict:!1,name:"MenuContext"}),A=M[0],O=M[1];function R(e){var t;return(0,o.Re)(e)&&!(null==(t=e.getAttribute("role"))||!t.startsWith("menuitem"))}function P(e,t){void 0===e&&(e={}),void 0===t&&(t=null);var n=e,i=n.onMouseEnter,r=n.onMouseMove,u=n.onMouseLeave,h=n.onClick,g=n.isDisabled,p=n.isFocusable,f=n.closeOnSelect,m=S(n,k),v=O(),_=v.setFocusedIndex,b=v.focusedIndex,w=v.closeOnSelect,x=v.onClose,L=v.menuRef,N=v.isOpen,E=v.menuId,D=s.useRef(null),I=E+"-menuitem-"+(0,y.Me)(),M=T({disabled:g&&!p}),A=M.index,P=M.register,F=s.useCallback((function(e){null==i||i(e),g||_(A)}),[_,A,g,i]),B=s.useCallback((function(e){null==r||r(e),D.current&&!(0,o.H9)(D.current)&&F(e)}),[F,r]),W=s.useCallback((function(e){null==u||u(e),g||_(-1)}),[_,g,u]),V=s.useCallback((function(e){null==h||h(e),R(e.currentTarget)&&(null!=f?f:w)&&x()}),[x,h,w,f]),z=A===b,H=g&&!p;return(0,y.rf)((function(){N&&(z&&!H&&D.current?(0,o.T_)(D.current,{nextTick:!0,selectTextIfInput:!1,preventScroll:!1}):L.current&&!(0,o.H9)(L.current)&&(0,o.T_)(L.current,{preventScroll:!1}))}),[z,H,L,N]),C({},m,function(e){void 0===e&&(e={});var t=e,n=t.ref,i=t.isDisabled,r=t.isFocusable,u=t.clickOnEnter,h=void 0===u||u,g=t.clickOnSpace,p=void 0===g||g,f=t.onMouseDown,m=t.onMouseUp,v=t.onClick,_=t.onKeyDown,b=t.onKeyUp,y=t.tabIndex,w=t.onMouseOver,C=t.onMouseLeave,S=function(e,t){if(null==e)return{};var n,i,o={},r=Object.keys(e);for(i=0;i=0||(o[n]=e[n]);return o}(t,c),x=s.useState(!0),k=x[0],L=x[1],N=s.useState(!1),E=N[0],D=N[1],I=function(){var e=s.useRef(new Map),t=e.current,n=s.useCallback((function(t,n,i,o){e.current.set(i,{type:n,el:t,options:o}),t.addEventListener(n,i,o)}),[]),i=s.useCallback((function(t,n,i,o){t.removeEventListener(n,i,o),e.current.delete(i)}),[]);return s.useEffect((function(){return function(){t.forEach((function(e,t){i(e.el,e.type,t,e.options)}))}}),[i,t]),{add:n,remove:i}}(),T=k?y:y||0,M=i&&!r,A=s.useCallback((function(e){if(i)return e.stopPropagation(),void e.preventDefault();e.currentTarget.focus(),null==v||v(e)}),[i,v]),O=s.useCallback((function(e){E&&d(e)&&(e.preventDefault(),e.stopPropagation(),D(!1),I.remove(document,"keyup",O,!1))}),[E,I]),R=s.useCallback((function(e){if(null==_||_(e),!(i||e.defaultPrevented||e.metaKey)&&d(e.nativeEvent)&&!k){var t=h&&"Enter"===e.key;p&&" "===e.key&&(e.preventDefault(),D(!0)),t&&(e.preventDefault(),e.currentTarget.click()),I.add(document,"keyup",O,!1)}}),[i,k,_,h,p,I,O]),P=s.useCallback((function(e){null==b||b(e),i||e.defaultPrevented||e.metaKey||d(e.nativeEvent)&&!k&&p&&" "===e.key&&(e.preventDefault(),D(!1),e.currentTarget.click())}),[p,k,i,b]),F=s.useCallback((function(e){0===e.button&&(D(!1),I.remove(document,"mouseup",F,!1))}),[I]),B=s.useCallback((function(e){if(!(0,o.n_)(e)){if(i)return e.stopPropagation(),void e.preventDefault();k||D(!0),e.currentTarget.focus({preventScroll:!0}),I.add(document,"mouseup",F,!1),null==f||f(e)}}),[i,k,f,I,F]),W=s.useCallback((function(e){(0,o.n_)(e)||(k||D(!1),null==m||m(e))}),[m,k]),V=s.useCallback((function(e){i?e.preventDefault():null==w||w(e)}),[i,w]),z=s.useCallback((function(e){E&&(e.preventDefault(),D(!1)),null==C||C(e)}),[E,C]),H=(0,a.lq)(n,(function(e){e&&"BUTTON"!==e.tagName&&L(!1)}));return l({},S,k?{ref:H,type:"button","aria-disabled":M?void 0:i,disabled:M,onClick:A,onMouseDown:f,onMouseUp:m,onKeyUp:b,onKeyDown:_,onMouseOver:w,onMouseLeave:C}:{ref:H,role:"button","data-active":(0,o.PB)(E),"aria-disabled":i?"true":void 0,tabIndex:M?void 0:T,onClick:A,onMouseDown:B,onMouseUp:W,onKeyUp:P,onKeyDown:R,onMouseOver:V,onMouseLeave:z})}({onClick:V,onMouseEnter:F,onMouseMove:B,onMouseLeave:W,ref:(0,a.lq)(P,D,t),isDisabled:g,isFocusable:p}),{id:I,role:"menuitem",tabIndex:z?0:-1})}var F=["descendants"],B=["children","as"],W=["rootProps"],V=["type"],z=["icon","iconSpacing","command","commandSpacing","children"],H=["icon","iconSpacing"],j=["title","children","className"],U=["className","children"],K=function(e){var t=e.children,n=(0,i.jC)("Menu",e),r=function(e){void 0===e&&(e={});var t=e,n=t.id,i=t.closeOnSelect,r=void 0===i||i,a=t.closeOnBlur,l=void 0===a||a,c=t.autoSelect,d=void 0===c||c,u=t.isLazy,h=t.isOpen,g=t.defaultIsOpen,p=t.onClose,f=t.onOpen,m=t.placement,v=void 0===m?"bottom-start":m,_=t.lazyBehavior,b=void 0===_?"unmount":_,k=t.direction,L=t.computePositionOnMount,N=void 0!==L&&L,E=S(t,x),D=s.useRef(null),T=s.useRef(null),M=I(),A=s.useCallback((function(){(0,o.T_)(D.current,{nextTick:!0,selectTextIfInput:!1})}),[]),O=s.useCallback((function(){var e=setTimeout((function(){var e=M.firstEnabled();e&&K(e.index)}));Y.current.add(e)}),[M]),R=s.useCallback((function(){var e=setTimeout((function(){var e=M.lastEnabled();e&&K(e.index)}));Y.current.add(e)}),[M]),P=s.useCallback((function(){null==f||f(),d?O():A()}),[d,O,A,f]),F=(0,y.qY)({isOpen:h,defaultIsOpen:g,onClose:p,onOpen:P}),B=F.isOpen,W=F.onOpen,V=F.onClose,z=F.onToggle;(0,y.O3)({enabled:B&&l,ref:D,handler:function(e){var t;null!=(t=T.current)&&t.contains(e.target)||V()}});var H=(0,w.D)(C({},E,{enabled:B||N,placement:v,direction:k})),j=s.useState(-1),U=j[0],K=j[1];(0,y.rf)((function(){B||K(-1)}),[B]),(0,y.Ck)(D,{focusRef:T,visible:B,shouldFocus:!0});var $=(0,y.ZS)(n,"menu-button","menu-list"),q=$[0],Z=$[1],G=s.useCallback((function(){W(),A()}),[W,A]),Y=s.useRef(new Set([]));return(0,y.zq)((function(){Y.current.forEach((function(e){return clearTimeout(e)})),Y.current.clear()})),{openAndFocusMenu:G,openAndFocusFirstItem:s.useCallback((function(){W(),O()}),[O,W]),openAndFocusLastItem:s.useCallback((function(){W(),R()}),[W,R]),onTransitionEnd:s.useCallback((function(){var e,t,n=(0,o.lZ)(D.current),i=null==(e=D.current)?void 0:e.contains(n.activeElement);if(B&&!i){var r=null==(t=M.item(U))?void 0:t.node;r&&(0,o.T_)(r,{selectTextIfInput:!1,preventScroll:!1})}}),[B,U,M]),descendants:M,popper:H,buttonId:q,menuId:Z,forceUpdate:H.forceUpdate,orientation:"vertical",isOpen:B,onToggle:z,onOpen:W,onClose:V,menuRef:D,buttonRef:T,focusedIndex:U,closeOnSelect:r,closeOnBlur:l,autoSelect:d,setFocusedIndex:K,isLazy:u,lazyBehavior:b}}(C({},(0,i.Lr)(e),{direction:(0,i.Fg)().direction})),a=r.descendants,l=S(r,F),c=s.useMemo((function(){return l}),[l]),d=c.isOpen,u=c.onClose,h=c.forceUpdate;return s.createElement(E,{value:a},s.createElement(A,{value:c},s.createElement(i.Fo,{value:n},(0,o.Pu)(t,{isOpen:d,onClose:u,forceUpdate:h}))))};o.Ts&&(K.displayName="Menu");var $=(0,i.Gp)((function(e,t){var n=(0,i.yK)();return s.createElement(i.m$.button,C({ref:t},e,{__css:C({display:"inline-flex",appearance:"none",alignItems:"center",outline:0},n.button)}))})),q=(0,i.Gp)((function(e,t){e.children;var n=e.as,r=function(e,t){void 0===e&&(e={}),void 0===t&&(t=null);var n=O(),i=n.onToggle,r=n.popper,l=n.openAndFocusFirstItem,c=n.openAndFocusLastItem,d=s.useCallback((function(e){var t=(0,o.uh)(e),n={Enter:l,ArrowDown:l,ArrowUp:c}[t];n&&(e.preventDefault(),e.stopPropagation(),n(e))}),[l,c]);return C({},e,{ref:(0,a.lq)(n.buttonRef,t,r.referenceRef),id:n.buttonId,"data-active":(0,o.PB)(n.isOpen),"aria-expanded":n.isOpen,"aria-haspopup":"menu","aria-controls":n.menuId,onClick:(0,o.v0)(e.onClick,i),onKeyDown:(0,o.v0)(e.onKeyDown,d)})}(S(e,B),t),l=n||$;return s.createElement(l,C({},r,{className:(0,o.cx)("chakra-menu__menu-button",e.className)}),s.createElement(i.m$.span,{__css:{pointerEvents:"none",flex:"1 1 auto",minW:0}},e.children))}));o.Ts&&(q.displayName="MenuButton");var Z={enter:{visibility:"visible",opacity:1,scale:1,transition:{duration:.2,ease:[.4,0,.2,1]}},exit:{transitionEnd:{visibility:"hidden"},opacity:0,scale:.8,transition:{duration:.1,easings:"easeOut"}}},G="custom"in r.E?r.E.custom(i.m$.div):(0,r.E)(i.m$.div),Y=(0,i.Gp)((function(e,t){var n,r,l=e.rootProps,c=S(e,W),d=O(),u=d.isOpen,h=d.onTransitionEnd,g=function(e,t){void 0===e&&(e={}),void 0===t&&(t=null);var n=O();if(!n)throw new Error("useMenuContext: context is undefined. Seems you forgot to wrap component within ");var i=n.focusedIndex,r=n.setFocusedIndex,l=n.menuRef,c=n.isOpen,d=n.onClose,u=n.menuId,h=n.isLazy,g=n.lazyBehavior,p=D(),f=(0,y.bx)({preventDefault:function(e){return" "!==e.key&&R(e.target)}}),m=s.useCallback((function(e){var t=(0,o.uh)(e),n={Tab:function(e){return e.preventDefault()},Escape:d,ArrowDown:function(){var e=p.nextEnabled(i);e&&r(e.index)},ArrowUp:function(){var e=p.prevEnabled(i);e&&r(e.index)}},s=n[t];if(s)return e.preventDefault(),void s(e);var a=f((function(e){var t=(0,o.LP)(p.values(),e,(function(e){var t,n;return null!=(t=null==e||null==(n=e.node)?void 0:n.textContent)?t:""}),p.item(i));if(t){var n=p.indexOf(t.node);r(n)}}));R(e.target)&&a(e)}),[p,i,f,d,r]),v=s.useRef(!1);c&&(v.current=!0);var _=(0,o.VI)({hasBeenSelected:v.current,isLazy:h,lazyBehavior:g,isSelected:c});return C({},e,{ref:(0,a.lq)(l,t),children:_?e.children:null,tabIndex:-1,role:"menu",id:u,style:C({},e.style,{transformOrigin:"var(--popper-transform-origin)"}),"aria-orientation":"vertical",onKeyDown:(0,o.v0)(e.onKeyDown,m)})}(c,t),p=function(e){void 0===e&&(e={});var t=O(),n=t.popper,i=t.isOpen;return n.getPopperProps(C({},e,{style:C({visibility:i?"visible":"hidden"},e.style)}))}(l),f=(0,i.yK)();return s.createElement(i.m$.div,C({},p,{__css:{zIndex:null!=(n=e.zIndex)?n:null==(r=f.list)?void 0:r.zIndex}}),s.createElement(G,C({},g,{onUpdate:h,className:(0,o.cx)("chakra-menu__menu-list",g.className),variants:Z,initial:!1,animate:u?"enter":"exit",__css:C({outline:0},f.list)})))}));o.Ts&&(Y.displayName="MenuList");var Q=(0,i.Gp)((function(e,t){var n=e.type,o=S(e,V),r=(0,i.yK)(),a=o.as?null!=n?n:void 0:"button",l=C({textDecoration:"none",color:"inherit",userSelect:"none",display:"flex",width:"100%",alignItems:"center",textAlign:"start",flex:"0 0 auto",outline:0},r.item);return s.createElement(i.m$.button,C({ref:t,type:a},o,{__css:l}))})),X=(0,i.Gp)((function(e,t){var n=e.icon,i=e.iconSpacing,r=void 0===i?"0.75rem":i,a=e.command,l=e.commandSpacing,c=void 0===l?"0.75rem":l,d=e.children,u=P(S(e,z),t),h=n||a?s.createElement("span",{style:{pointerEvents:"none",flex:1}},d):d;return s.createElement(Q,C({},u,{className:(0,o.cx)("chakra-menu__menuitem",u.className)}),n&&s.createElement(ie,{fontSize:"0.8em",marginEnd:r},n),h,a&&s.createElement(ne,{marginStart:c},a))}));o.Ts&&(X.displayName="MenuItem");var J=function(e){return s.createElement("svg",C({viewBox:"0 0 14 14",width:"1em",height:"1em"},e),s.createElement("polygon",{fill:"currentColor",points:"5.5 11.9993304 14 3.49933039 12.5 2 5.5 8.99933039 1.5 4.9968652 0 6.49933039"}))},ee=(0,i.Gp)((function(e,t){var n=e.icon,i=e.iconSpacing,r=void 0===i?"0.75rem":i,a=S(e,H),l=function(e,t){void 0===e&&(e={}),void 0===t&&(t=null);var n=e,i=n.type,o=void 0===i?"radio":i,r=n.isChecked;return C({},P(S(n,L),t),{role:"menuitem"+o,"aria-checked":r})}(a,t);return s.createElement(Q,C({},l,{className:(0,o.cx)("chakra-menu__menuitem-option",a.className)}),s.createElement(ie,{fontSize:"0.8em",marginEnd:r,opacity:e.isChecked?1:0},n||s.createElement(J,null)),s.createElement("span",{style:{flex:1}},l.children))}));ee.id="MenuItemOption",o.Ts&&(ee.displayName="MenuItemOption"),o.Ts;var te=(0,i.Gp)((function(e,t){var n=e.title,r=e.children,a=e.className,l=S(e,j),c=(0,o.cx)("chakra-menu__group__title",a),d=(0,i.yK)();return s.createElement("div",{ref:t,className:"chakra-menu__group",role:"group"},n&&s.createElement(i.m$.p,C({className:c},l,{__css:d.groupTitle}),n),r)}));o.Ts&&(te.displayName="MenuGroup");var ne=(0,i.Gp)((function(e,t){var n=(0,i.yK)();return s.createElement(i.m$.span,C({ref:t},e,{__css:n.command,className:"chakra-menu__command"}))}));o.Ts&&(ne.displayName="MenuCommand");var ie=function(e){var t=e.className,n=e.children,r=S(e,U),a=s.Children.only(n),l=s.isValidElement(a)?s.cloneElement(a,{focusable:"false","aria-hidden":!0,className:(0,o.cx)("chakra-menu__icon",a.props.className)}):null,c=(0,o.cx)("chakra-menu__icon-wrapper",t);return s.createElement(i.m$.span,C({className:c},r,{__css:{flexShrink:0}}),l)};o.Ts&&(ie.displayName="MenuIcon"),o.Ts},68016:(e,t,n)=>{"use strict";n.d(t,{u_:()=>rn,fe:()=>un,ol:()=>gn,hz:()=>an,mz:()=>hn,xB:()=>dn,ZA:()=>cn});var i=n(84746),o=n(67294),r=n(87462),s=(n(45697),"data-focus-lock"),a="data-focus-lock-disabled";function l(e,t){return n=t,i=function(t){return e.forEach((function(e){return function(e,t){return"function"==typeof e?e(t):e&&(e.current=t),e}(e,t)}))},(r=(0,o.useState)((function(){return{value:n,callback:i,facade:{get current(){return r.value},set current(e){var t=r.value;t!==e&&(r.value=e,r.callback(e,t))}}}}))[0]).callback=i,r.facade;var n,i,r}var c={width:"1px",height:"0px",padding:0,overflow:"hidden",position:"fixed",top:"1px",left:"1px"},d=function(e){var t=e.children;return o.createElement(o.Fragment,null,o.createElement("div",{key:"guard-first","data-focus-guard":!0,"data-focus-auto-guard":!0,style:c}),t,t&&o.createElement("div",{key:"guard-last","data-focus-guard":!0,"data-focus-auto-guard":!0,style:c}))};d.propTypes={},d.defaultProps={children:null};var u=function(){return u=Object.assign||function(e){for(var t,n=1,i=arguments.length;n1?L(e[0],e):e[0]},E=function(e,t){return e.length>1?e.indexOf(L(e[t],e)):t},D=function(e,t){var n=e.get(t);if(void 0!==n)return n;var i=function(e,t){return!e||e===document||e&&e.nodeType===Node.DOCUMENT_NODE||!function(e){if(e.nodeType!==Node.ELEMENT_NODE)return!1;var t=window.getComputedStyle(e,null);return!(!t||!t.getPropertyValue||"none"!==t.getPropertyValue("display")&&"hidden"!==t.getPropertyValue("visibility"))}(e)&&t(e.parentNode&&e.parentNode.nodeType===Node.DOCUMENT_FRAGMENT_NODE?e.parentNode.host:e.parentNode)}(t,D.bind(void 0,e));return e.set(t,i),i},I=function(e){return Boolean(e&&e.dataset&&e.dataset.focusGuard)},T=function(e){return!I(e)},M=function(e){return Boolean(e)},A="NEW_FOCUS",O=function(e){for(var t=Array(e.length),n=0;n0&&t.add(o),(r&Node.DOCUMENT_POSITION_CONTAINS)>0&&t.add(i)}return e.filter((function(e,n){return!t.has(n)}))}(O(P(t).querySelectorAll('[data-focus-lock="'+n+'"]:not(['+a+'="disabled"])'))):[t]),e}),[])},B=function(e,t){var n=e.tabIndex-t.tabIndex,i=e.index-t.index;if(n){if(!e.tabIndex)return 1;if(!t.tabIndex)return-1}return n||i},W=function(e,t,n){return O(e).map((function(e,t){return{node:e,index:t,tabIndex:n&&-1===e.tabIndex?(e.dataset||{}).focusGuard?0:-1:e.tabIndex}})).filter((function(e){return!t||e.tabIndex>=0})).sort(B)},V=["button:enabled","select:enabled","textarea:enabled","input:enabled","a[href]","area[href]","summary","iframe","object","embed","audio[controls]","video[controls]","[tabindex]","[contenteditable]","[autofocus]"].join(","),z=V+", [data-focus-guard]",H=function(e,t){return e.reduce((function(e,n){return e.concat(O(n.querySelectorAll(t?z:V)),n.parentNode?O(n.parentNode.querySelectorAll(V)).filter((function(e){return e===n})):[])}),[])},j=function(e,t){return O(e).filter((function(e){return D(t,e)})).filter((function(e){return function(e){return!(("INPUT"===e.tagName||"BUTTON"===e.tagName)&&("hidden"===e.type||e.disabled))}(e)}))},U=function(e,t,n){return W(j(H(e,n),t),!0,n)},K=function(e,t){return W(j(H(e),t),!1)},$=function(e,t){return void 0===t&&(t=[]),t.push(e),e.parentNode&&$(e.parentNode,t),t},q=function(e,t){for(var n=$(e),i=$(t),o=0;o=0)return r}return!1},Z=function(e,t,n){var i=R(e),o=R(t),r=i[0],s=!1;return o.filter(Boolean).forEach((function(e){s=q(s||e,e)||s,n.filter(Boolean).forEach((function(e){var t=q(r,e);t&&(s=!s||t.contains(s)?t:q(t,s))}))})),s},G=function(e,t){var n=document&&document.activeElement,i=F(e).filter(T),o=Z(n||e,e,i),r=new Map,s=K(i,r),a=U(i,r).filter((function(e){var t=e.node;return T(t)}));if(a[0]||(a=s)[0]){var l,c,d,u,h=K([o],r).map((function(e){return e.node})),g=(l=h,c=a,d=new Map,c.forEach((function(e){return d.set(e.node,e)})),l.map((function(e){return d.get(e)})).filter(M)),p=g.map((function(e){return e.node})),f=function(e,t,n,i){var o=e.length,r=e[0],s=e[o-1],a=I(n);if(!(e.indexOf(n)>=0)){var l,c,d=t.indexOf(n),u=i?t.indexOf(i):d,h=i?e.indexOf(i):-1,g=d-u,p=t.indexOf(r),f=t.indexOf(s),m=(l=t,c=new Set,l.forEach((function(e){return c.add(L(e,l))})),l.filter((function(e){return c.has(e)}))),v=m.indexOf(n)-(i?m.indexOf(i):d),_=E(e,0),b=E(e,o-1);return-1===d||-1===h?A:!g&&h>=0?h:d<=p&&a&&Math.abs(g)>1?b:d>=f&&a&&Math.abs(g)>1?_:g&&Math.abs(v)>1?h:d<=p?b:d>f?_:g?Math.abs(g)>1?h:(o+h+g)%o:void 0}}(p,h,n,t);if(f===A){var m=s.map((function(e){return e.node})).filter((u=function(e,t){return e.reduce((function(e,n){return e.concat(function(e,t){return j((n=e.querySelectorAll("[data-autofocus-inside]"),O(n).map((function(e){return H([e])})).reduce((function(e,t){return e.concat(t)}),[])),t);var n}(n,t))}),[])}(i,r),function(e){return e.autofocus||e.dataset&&!!e.dataset.autofocus||u.indexOf(e)>=0}));return{node:m&&m.length?N(m):N(p)}}return void 0===f?f:g[f]}},Y=0,Q=!1;const X=function(e,t){var n,i=G(e,t);if(!Q&&i){if(Y>2)return console.error("FocusLock: focus-fighting detected. Only one focus management system could be active. See https://github.com/theKashey/focus-lock/#focus-fighting"),Q=!0,void setTimeout((function(){Q=!1}),1);Y++,(n=i.node).focus(),"contentWindow"in n&&n.contentWindow&&n.contentWindow.focus(),Y--}};var J=function(e){var t=document&&document.activeElement;return!(!t||t.dataset&&t.dataset.focusGuard)&&F(e).reduce((function(e,n){return e||n.contains(t)||function(e){return Boolean(O(e.querySelectorAll("iframe")).some((function(e){return e===document.activeElement})))}(n)}),!1)};function ee(e){var t=window.setImmediate;void 0!==t?t(e):setTimeout(e,1)}var te=null,ne=null,ie=null,oe=!1,re=function(){return!0};function se(e,t,n,i){var o=null,r=e;do{var s=i[r];if(s.guard)s.node.dataset.focusAutoGuard&&(o=s);else{if(!s.lockItem)break;if(r!==e)return;o=null}}while((r+=n)!==t);o&&(o.node.tabIndex=0)}var ae=function(e){return e&&"current"in e?e.current:e},le=function(){var e,t,n,i,o,r,s,a=!1;if(te){var l=te,c=l.observed,d=l.persistentFocus,u=l.autoFocus,h=l.shards,g=l.crossFrame,p=c||ie&&ie.portaledElement,f=document&&document.activeElement;if(p){var m=[p].concat(h.map(ae).filter(Boolean));if(f&&!function(e){return(te.whiteList||re)(e)}(f)||(d||(g?Boolean(oe):"meanwhile"===oe)||!(document&&document.activeElement===document.body||document&&O(document.querySelectorAll("[data-no-focus-lock]")).some((function(e){return e.contains(document.activeElement)})))||!ne&&u)&&(!p||J(m)||(s=f,ie&&ie.portaledElement===s)||(document&&!ne&&f&&!u?(f.blur&&f.blur(),document.body.focus()):(a=X(m,ne),ie={})),oe=!1,ne=document&&document.activeElement),document){var v=document&&document.activeElement,_=(t=F(e=m).filter(T),n=Z(e,e,t),i=new Map,o=U([n],i,!0),r=U(t,i).filter((function(e){var t=e.node;return T(t)})).map((function(e){return e.node})),o.map((function(e){var t=e.node;return{node:t,index:e.index,lockItem:r.indexOf(t)>=0,guard:I(t)}}))),b=_.map((function(e){return e.node})).indexOf(v);b>-1&&(_.filter((function(e){var t=e.guard,n=e.node;return t&&n.dataset.focusAutoGuard})).forEach((function(e){return e.node.removeAttribute("tabIndex")})),se(b,_.length,1,_),se(b,-1,-1,_))}}}return a},ce=function(e){le()&&e&&(e.stopPropagation(),e.preventDefault())},de=function(){return ee(le)},ue=function(){oe="just",setTimeout((function(){oe="meanwhile"}),0)};m.assignSyncMedium((function(e){var t=e.target,n=e.currentTarget;n.contains(t)||(ie={observerNode:n,portaledElement:t})})),v.assignMedium(de),_.assignMedium((function(e){return e({moveFocusInside:X,focusInside:J})}));const he=(ge=function(e){return e.filter((function(e){return!e.disabled}))},pe=function(e){var t=e.slice(-1)[0];t&&!te&&(document.addEventListener("focusin",ce,!0),document.addEventListener("focusout",de),window.addEventListener("blur",ue));var n=te,i=n&&t&&t.id===n.id;te=t,n&&!i&&(n.onDeactivation(),e.filter((function(e){return e.id===n.id})).length||n.returnFocus(!t)),t?(ne=null,i&&n.observed===t.observed||t.onActivation(),le(),ee(le)):(document.removeEventListener("focusin",ce,!0),document.removeEventListener("focusout",de),window.removeEventListener("blur",ue),ne=null)},function(e){var t,n=[];function i(){t=ge(n.map((function(e){return e.props}))),pe(t)}var r=function(r){var s,a;function l(){return r.apply(this,arguments)||this}a=r,(s=l).prototype=Object.create(a.prototype),s.prototype.constructor=s,S(s,a),l.peek=function(){return t};var c=l.prototype;return c.componentDidMount=function(){n.push(this),i()},c.componentDidUpdate=function(){i()},c.componentWillUnmount=function(){var e=n.indexOf(this);n.splice(e,1),i()},c.render=function(){return o.createElement(e,this.props)},l}(o.PureComponent);return(0,x.Z)(r,"displayName","SideEffect("+function(e){return e.displayName||e.name||"Component"}(e)+")"),r})((function(){return null}));var ge,pe,fe=o.forwardRef((function(e,t){return o.createElement(C,(0,r.Z)({sideCar:he,ref:t},e))})),me=C.propTypes||{};me.sideCar,function(e,t){if(null==e)return{};var n,i,o={},r=Object.keys(e);for(i=0;i=0||(o[n]=e[n])}(me,["sideCar"]),fe.propTypes={};const ve=fe;var _e=n(44592),be=function(e){var t=e.initialFocusRef,n=e.finalFocusRef,i=e.contentRef,r=e.restoreFocus,s=e.children,a=e.isDisabled,l=e.autoFocus,c=e.persistentFocus,d=e.lockFocusAcrossFrames,u=o.useCallback((function(){null!=t&&t.current?t.current.focus():null!=i&&i.current&&0===(0,_e.t5)(i.current).length&&(0,_e.T_)(i.current,{nextTick:!0})}),[t,i]),h=o.useCallback((function(){var e;null==n||null==(e=n.current)||e.focus()}),[n]),g=r&&!n;return o.createElement(ve,{crossFrame:d,persistentFocus:c,autoFocus:l,disabled:a,onActivation:u,onDeactivation:h,returnFocus:g},s)};_e.Ts&&(be.displayName="FocusLock");var ye=n(46871),we=n(105),Ce=n(38554),Se=n.n(Ce),xe=n(53869),ke=n(99860);function Le(e,t){if(null==e)return{};var n,i,o={},r=Object.keys(e);for(i=0;i=0||(o[n]=e[n]);return o}function Ne(){return Ne=Object.assign||function(e){for(var t=1;t0?1:0)},{overflow:"hidden",height:o,transitionEnd:null==s?void 0:s.exit,transition:null!=(t=null==r?void 0:r.exit)?t:Pe(Be.exit,a)})},enter:function(e){var t,n=e.animateOpacity,i=e.endingHeight,o=e.transition,r=e.transitionEnd,s=e.delay;return Ne({},n&&{opacity:1},{height:i,transitionEnd:null==r?void 0:r.enter,transition:null!=(t=null==o?void 0:o.enter)?t:Re(Be.enter,s)})}},Ve=o.forwardRef((function(e,t){var n=e.in,i=e.unmountOnExit,r=e.animateOpacity,s=void 0===r||r,a=e.startingHeight,l=void 0===a?0:a,c=e.endingHeight,d=void 0===c?"auto":c,u=e.style,h=e.className,g=e.transition,p=e.transitionEnd,f=Le(e,Fe),m=o.useState(!1),v=m[0],_=m[1];o.useEffect((function(){var e=setTimeout((function(){_(!0)}));return function(){return clearTimeout(e)}}),[]),(0,_e.ZK)({condition:Boolean(l>0&&i),message:"startingHeight and unmountOnExit are mutually exclusive. You can't use them together"});var b=parseFloat(l.toString())>0,y={startingHeight:l,endingHeight:d,animateOpacity:s,transition:v?g:{enter:{duration:0}},transitionEnd:Se()(p,{enter:{overflow:"initial"},exit:i?void 0:{display:b?"block":"none"}})},w=!i||n,C=n||i?"enter":"exit";return o.createElement(xe.M,{initial:!1,custom:y},w&&o.createElement(ke.E.div,Ne({ref:t},f,{className:(0,_e.cx)("chakra-collapse",h),style:Ne({overflow:"hidden",display:"block"},u),custom:y,variants:We,initial:!!i&&"exit",animate:C,exit:"exit"})))}));_e.Ts&&(Ve.displayName="Collapse");var ze=["unmountOnExit","in","className","transition","transitionEnd","delay"],He={enter:function(e){var t,n=void 0===e?{}:e,i=n.transition,o=n.transitionEnd,r=n.delay;return{opacity:1,transition:null!=(t=null==i?void 0:i.enter)?t:Re(Oe.enter,r),transitionEnd:null==o?void 0:o.enter}},exit:function(e){var t,n=void 0===e?{}:e,i=n.transition,o=n.transitionEnd,r=n.delay;return{opacity:0,transition:null!=(t=null==i?void 0:i.exit)?t:Pe(Oe.exit,r),transitionEnd:null==o?void 0:o.exit}}},je={initial:"exit",animate:"enter",exit:"exit",variants:He},Ue=o.forwardRef((function(e,t){var n=e.unmountOnExit,i=e.in,r=e.className,s=e.transition,a=e.transitionEnd,l=e.delay,c=Le(e,ze),d=i||n?"enter":"exit",u=!n||i&&n,h={transition:s,transitionEnd:a,delay:l};return o.createElement(xe.M,{custom:h},u&&o.createElement(ke.E.div,Ne({ref:t,className:(0,_e.cx)("chakra-fade",r),custom:h},je,{animate:d},c)))}));_e.Ts&&(Ue.displayName="Fade");var Ke=["unmountOnExit","in","reverse","initialScale","className","transition","transitionEnd","delay"],$e={exit:function(e){var t,n=e.reverse,i=e.initialScale,o=e.transition,r=e.transitionEnd,s=e.delay;return Ne({opacity:0},n?{scale:i,transitionEnd:null==r?void 0:r.exit}:{transitionEnd:Ne({scale:i},null==r?void 0:r.exit)},{transition:null!=(t=null==o?void 0:o.exit)?t:Pe(Oe.exit,s)})},enter:function(e){var t,n=e.transitionEnd,i=e.transition,o=e.delay;return{opacity:1,scale:1,transition:null!=(t=null==i?void 0:i.enter)?t:Re(Oe.enter,o),transitionEnd:null==n?void 0:n.enter}}},qe={initial:"exit",animate:"enter",exit:"exit",variants:$e},Ze=o.forwardRef((function(e,t){var n=e.unmountOnExit,i=e.in,r=e.reverse,s=void 0===r||r,a=e.initialScale,l=void 0===a?.95:a,c=e.className,d=e.transition,u=e.transitionEnd,h=e.delay,g=Le(e,Ke),p=!n||i&&n,f=i||n?"enter":"exit",m={initialScale:l,reverse:s,transition:d,transitionEnd:u,delay:h};return o.createElement(xe.M,{custom:m},p&&o.createElement(ke.E.div,Ne({ref:t,className:(0,_e.cx)("chakra-offset-slide",c)},qe,{animate:f,custom:m},g)))}));_e.Ts&&(Ze.displayName="ScaleFade");var Ge=["direction","style","unmountOnExit","in","className","transition","transitionEnd","delay"],Ye={exit:{duration:.15,ease:Ee.easeInOut},enter:{type:"spring",damping:25,stiffness:180}},Qe={exit:function(e){var t,n=e.direction,i=e.transition,o=e.transitionEnd,r=e.delay;return Ne({},Ae({direction:n}).exit,{transition:null!=(t=null==i?void 0:i.exit)?t:Pe(Ye.exit,r),transitionEnd:null==o?void 0:o.exit})},enter:function(e){var t,n=e.direction,i=e.transitionEnd,o=e.transition,r=e.delay;return Ne({},Ae({direction:n}).enter,{transition:null!=(t=null==o?void 0:o.enter)?t:Re(Ye.enter,r),transitionEnd:null==i?void 0:i.enter})}},Xe=o.forwardRef((function(e,t){var n=e.direction,i=void 0===n?"right":n,r=e.style,s=e.unmountOnExit,a=e.in,l=e.className,c=e.transition,d=e.transitionEnd,u=e.delay,h=Le(e,Ge),g=Ae({direction:i}),p=Object.assign({position:"fixed"},g.position,r),f=!s||a&&s,m=a||s?"enter":"exit",v={transitionEnd:d,transition:c,direction:i,delay:u};return o.createElement(xe.M,{custom:v},f&&o.createElement(ke.E.div,Ne({ref:t,initial:"exit",className:(0,_e.cx)("chakra-slide",l),animate:m,exit:"exit",custom:v,variants:Qe,style:p},h)))}));_e.Ts&&(Xe.displayName="Slide");var Je=["unmountOnExit","in","reverse","className","offsetX","offsetY","transition","transitionEnd","delay"],et={initial:function(e){var t,n=e.offsetX,i=e.offsetY,o=e.transition,r=e.transitionEnd,s=e.delay;return{opacity:0,x:n,y:i,transition:null!=(t=null==o?void 0:o.exit)?t:Pe(Oe.exit,s),transitionEnd:null==r?void 0:r.exit}},enter:function(e){var t,n=e.transition,i=e.transitionEnd,o=e.delay;return{opacity:1,x:0,y:0,transition:null!=(t=null==n?void 0:n.enter)?t:Re(Oe.enter,o),transitionEnd:null==i?void 0:i.enter}},exit:function(e){var t,n=e.offsetY,i=e.offsetX,o=e.transition,r=e.transitionEnd,s=e.reverse,a=e.delay,l={x:i,y:n};return Ne({opacity:0,transition:null!=(t=null==o?void 0:o.exit)?t:Pe(Oe.exit,a)},s?Ne({},l,{transitionEnd:null==r?void 0:r.exit}):{transitionEnd:Ne({},l,null==r?void 0:r.exit)})}},tt={initial:"initial",animate:"enter",exit:"exit",variants:et},nt=o.forwardRef((function(e,t){var n=e.unmountOnExit,i=e.in,r=e.reverse,s=void 0===r||r,a=e.className,l=e.offsetX,c=void 0===l?0:l,d=e.offsetY,u=void 0===d?8:d,h=e.transition,g=e.transitionEnd,p=e.delay,f=Le(e,Je),m=!n||i&&n,v=i||n?"enter":"exit",_={offsetX:c,offsetY:u,reverse:s,transition:h,transitionEnd:g,delay:p};return o.createElement(xe.M,{custom:_},m&&o.createElement(ke.E.div,Ne({ref:t,className:(0,_e.cx)("chakra-offset-slide",a),custom:_},tt,{animate:v},f)))}));_e.Ts&&(nt.displayName="SlideFade");var it=n(26450),ot=n(69283),rt=function(){return rt=Object.assign||function(e){for(var t,n=1,i=arguments.length;n