Option sets: a .o target for shared parameters
A named group of optional parameters, declared once and used by several
klammers, so a writer learns one vocabulary instead of a spelling per
klammer. The "o" target is a pseudo-target beside "k": "k" declares a
klammer's interface and documents it, "o" declares an option interface and
documents it, and neither produces output for any target.
@@caption_args.o :caption :number.bool true :caption_side.side
: Arguments that define a caption for a block element @@
@@code.k :filename @hpos_args :hpos left @ @caption_args :caption_side top @
| text.literal : A source file displayed verbatim @@
A set is used only in the parameter list of a ".k" declaration -- the one
place a klammer's interface is declared once for all of its targets -- and
is resolved as that list is read. Names and types come from the set; a
default may be overridden where it is used. A klammer application in a
parameter list is now a definition-time error.
The SKS gains the sets caption_args and hpos_args (:hpos and :offset), and
@table, @image, @image_grid, @reference and @show gain .k declarations. A
distance is no longer written as a position: :hpos 4em is rejected, and the
same layout is :hpos left :offset 4em. Code listings are numbered by
default, like tables and figures.
New engine sources mac/option_set{,_registry}.{h,cpp}; tst/ ships two more
suites, option_set_test.sh and signature_test.sh (twelve in all).
(from dev 34e536cb0329)
2026-08-06 13:11:37 +02:00
|
|
|
#!/bin/bash
|
|
|
|
|
#
|
|
|
|
|
# option_set_test.sh — Regression tests for option sets (the ".o" target).
|
|
|
|
|
#
|
|
|
|
|
# An option set is a named group of OPTIONAL parameters, declared once and
|
|
|
|
|
# used by several klammers, so that a writer learns one vocabulary instead of
|
|
|
|
|
# a spelling per klammer:
|
|
|
|
|
#
|
|
|
|
|
# @@caption_args.o :caption :number.bool true : A caption @@
|
|
|
|
|
# @@table.k rows.rest(2) @caption_args@ : A table of rows of cells @@
|
|
|
|
|
#
|
|
|
|
|
# The rules this suite holds to:
|
|
|
|
|
#
|
|
|
|
|
# * "o" is a pseudo-target beside "k". A ".o" declaration defines no
|
|
|
|
|
# klammer and produces no output for any target.
|
|
|
|
|
# * A set declares optional parameters only. A positional is not
|
|
|
|
|
# writer-facing, so there is nothing for a set to standardize.
|
|
|
|
|
# * Names and types come from the set; a DEFAULT may be overridden where
|
|
|
|
|
# the set is used, because what varies between klammers is only what
|
|
|
|
|
# silence means for that one klammer.
|
|
|
|
|
# * A set may be used only in the parameter list of a ".k" declaration --
|
|
|
|
|
# the one place a klammer's interface is declared once for all of its
|
|
|
|
|
# targets. Not in a per-target definition, and not in another set.
|
|
|
|
|
# * A klammer application in a parameter list is an error. Splicing a
|
|
|
|
|
# constant klammer there used to be the way to share parameters, and in
|
|
|
|
|
# a ".k" declaration it silently destroyed the whole parameter list.
|
|
|
|
|
#
|
|
|
|
|
# Engine tier: no SKS. Every fixture defines its own target inline.
|
|
|
|
|
#
|
|
|
|
|
# Usage: ./option_set_test.sh
|
|
|
|
|
# Exit code: 0 if all tests pass, 1 otherwise.
|
|
|
|
|
|
|
|
|
|
PASS=0
|
|
|
|
|
FAIL=0
|
|
|
|
|
KTEXT=ktext
|
|
|
|
|
K=${KLAMMERTEXT_HOME:?KLAMMERTEXT_HOME must be set}
|
|
|
|
|
|
|
|
|
|
red=$'\033[31m'
|
|
|
|
|
green=$'\033[32m'
|
|
|
|
|
bold=$'\033[1m'
|
|
|
|
|
reset=$'\033[0m'
|
|
|
|
|
|
|
|
|
|
# The fixture prelude: a target, and two sets to use in declarations.
|
|
|
|
|
PRELUDE='@@@target fix | a fixture target @@@
|
|
|
|
|
@@cap.o :caption :number.bool true :side bottom : A caption for an element @@
|
|
|
|
|
@@pos.o :hpos left : Where an element sits @@'
|
|
|
|
|
|
|
|
|
|
# check_eq NAME EXPECTED SOURCE [TARGET] — render SOURCE (for the fix target
|
|
|
|
|
# unless TARGET says otherwise) and compare the trimmed output with EXPECTED.
|
|
|
|
|
check_eq() {
|
|
|
|
|
local name="$1" expected="$2" source="$3" target="${4:-fix}"
|
|
|
|
|
local output status
|
An output policy for the three commands, and @cond as a true special form
A snapshot of the development tree. The substantial changes since the last one:
COMMAND OUTPUT POLICY. The three commands display text in exactly three cases,
and each owns a stream: LOGGING under "-v" greater than 0 and an ERROR before
termination go to STDERR; OUTPUT THE USER ASKED FOR goes to STDOUT. For ktext
that output is a document, so "ktext doc.kt -d | ..." is now safe -- logging
used to share the stream and land inside the document. A bare command prints
its usage and succeeds rather than failing. Colour is emitted only to a
terminal, per stream, and NO_COLOR is honoured.
"-v 1" reports every decision whose outcome you could not have read off your own
input: the klammerset that was loaded and from which file, a font's directory, a
":files" name's file, how "-o" was expanded. Higher levels are the trace.
The commands no longer warn and continue: an anomaly is an error, described with
its location. Two exceptions remain, each for a stated reason -- a condition
that is expected and temporary by design, and a judgment that is a heuristic
rather than exact.
@cond IS NOW A TRUE SPECIAL FORM, resolved at APPLICATION time rather than when
the file is read. Two consequences for a writer:
* a state variable reaches the predicate. "@@@state Flag :value true @@@
@cond *Flag* | T | F @" renders "T"; it used to see the literal "*Flag*" and
silently take the false branch. The document now behaves like a klammer
body, whose arguments are bound before its conditionals are decided.
* nothing in a discarded branch happens -- it is not read, not evaluated, not
expanded. An @eval in the branch not taken used to run anyway.
Its predicate relation is total and strict: true, True, 1; false, False, 0, and
empty; anything else is an error at the @cond rather than silently false.
@eval REACHING OUTSIDE. ":shell" and ":haskell" now keep the command's standard
error out of the document (it appears under "-v 1") and treat a nonzero exit as
an error naming what the command reported. A command that exits nonzero on
purpose -- "grep" finding no match -- says so with "|| true".
KLAMMER SETS. Several combine: "--klammersets a b c" loads all three in the
order given, sharing one namespace, with the definition modes deciding
collisions. "none" means none and may not be combined with other symbols. A
klammerset with symbol X is declared in a file X/X.k, which is what lets two
sets require the same third set without loading it twice.
TESTS. Four new suites: the kdiag command's interface, the @eval primitive's
contract with the outside world, and verbosity at both tiers. Three suites
that could not run on macOS at all now do.
Assembled from dev commit 6c8ee6c22fca.
2026-08-16 01:37:59 +02:00
|
|
|
output=$("$KTEXT" --klammersets none -s "$PRELUDE
|
Option sets: a .o target for shared parameters
A named group of optional parameters, declared once and used by several
klammers, so a writer learns one vocabulary instead of a spelling per
klammer. The "o" target is a pseudo-target beside "k": "k" declares a
klammer's interface and documents it, "o" declares an option interface and
documents it, and neither produces output for any target.
@@caption_args.o :caption :number.bool true :caption_side.side
: Arguments that define a caption for a block element @@
@@code.k :filename @hpos_args :hpos left @ @caption_args :caption_side top @
| text.literal : A source file displayed verbatim @@
A set is used only in the parameter list of a ".k" declaration -- the one
place a klammer's interface is declared once for all of its targets -- and
is resolved as that list is read. Names and types come from the set; a
default may be overridden where it is used. A klammer application in a
parameter list is now a definition-time error.
The SKS gains the sets caption_args and hpos_args (:hpos and :offset), and
@table, @image, @image_grid, @reference and @show gain .k declarations. A
distance is no longer written as a position: :hpos 4em is rejected, and the
same layout is :hpos left :offset 4em. Code listings are numbered by
default, like tables and figures.
New engine sources mac/option_set{,_registry}.{h,cpp}; tst/ ships two more
suites, option_set_test.sh and signature_test.sh (twelve in all).
(from dev 34e536cb0329)
2026-08-06 13:11:37 +02:00
|
|
|
$source" -t "$target" -d 2>&1)
|
|
|
|
|
status=$?
|
|
|
|
|
output=$(printf '%s' "$output" | tr -d '\n' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
|
|
|
|
|
if [ $status -ne 0 ]; then
|
|
|
|
|
echo "${red}FAIL${reset} $name — ktext exited $status"
|
|
|
|
|
echo " output: $(printf '%s' "$output" | head -3)"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
if [ "$output" = "$expected" ]; then
|
|
|
|
|
echo "${green}PASS${reset} $name"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} $name"
|
|
|
|
|
echo " expected: [$expected]"
|
|
|
|
|
echo " got: [$output]"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# check_fails NAME SUBSTRING SOURCE — SOURCE must be rejected, with a
|
|
|
|
|
# message containing SUBSTRING.
|
|
|
|
|
check_fails() {
|
|
|
|
|
local name="$1" needle="$2" source="$3"
|
|
|
|
|
local output status
|
An output policy for the three commands, and @cond as a true special form
A snapshot of the development tree. The substantial changes since the last one:
COMMAND OUTPUT POLICY. The three commands display text in exactly three cases,
and each owns a stream: LOGGING under "-v" greater than 0 and an ERROR before
termination go to STDERR; OUTPUT THE USER ASKED FOR goes to STDOUT. For ktext
that output is a document, so "ktext doc.kt -d | ..." is now safe -- logging
used to share the stream and land inside the document. A bare command prints
its usage and succeeds rather than failing. Colour is emitted only to a
terminal, per stream, and NO_COLOR is honoured.
"-v 1" reports every decision whose outcome you could not have read off your own
input: the klammerset that was loaded and from which file, a font's directory, a
":files" name's file, how "-o" was expanded. Higher levels are the trace.
The commands no longer warn and continue: an anomaly is an error, described with
its location. Two exceptions remain, each for a stated reason -- a condition
that is expected and temporary by design, and a judgment that is a heuristic
rather than exact.
@cond IS NOW A TRUE SPECIAL FORM, resolved at APPLICATION time rather than when
the file is read. Two consequences for a writer:
* a state variable reaches the predicate. "@@@state Flag :value true @@@
@cond *Flag* | T | F @" renders "T"; it used to see the literal "*Flag*" and
silently take the false branch. The document now behaves like a klammer
body, whose arguments are bound before its conditionals are decided.
* nothing in a discarded branch happens -- it is not read, not evaluated, not
expanded. An @eval in the branch not taken used to run anyway.
Its predicate relation is total and strict: true, True, 1; false, False, 0, and
empty; anything else is an error at the @cond rather than silently false.
@eval REACHING OUTSIDE. ":shell" and ":haskell" now keep the command's standard
error out of the document (it appears under "-v 1") and treat a nonzero exit as
an error naming what the command reported. A command that exits nonzero on
purpose -- "grep" finding no match -- says so with "|| true".
KLAMMER SETS. Several combine: "--klammersets a b c" loads all three in the
order given, sharing one namespace, with the definition modes deciding
collisions. "none" means none and may not be combined with other symbols. A
klammerset with symbol X is declared in a file X/X.k, which is what lets two
sets require the same third set without loading it twice.
TESTS. Four new suites: the kdiag command's interface, the @eval primitive's
contract with the outside world, and verbosity at both tiers. Three suites
that could not run on macOS at all now do.
Assembled from dev commit 6c8ee6c22fca.
2026-08-16 01:37:59 +02:00
|
|
|
output=$("$KTEXT" --klammersets none -s "$PRELUDE
|
Option sets: a .o target for shared parameters
A named group of optional parameters, declared once and used by several
klammers, so a writer learns one vocabulary instead of a spelling per
klammer. The "o" target is a pseudo-target beside "k": "k" declares a
klammer's interface and documents it, "o" declares an option interface and
documents it, and neither produces output for any target.
@@caption_args.o :caption :number.bool true :caption_side.side
: Arguments that define a caption for a block element @@
@@code.k :filename @hpos_args :hpos left @ @caption_args :caption_side top @
| text.literal : A source file displayed verbatim @@
A set is used only in the parameter list of a ".k" declaration -- the one
place a klammer's interface is declared once for all of its targets -- and
is resolved as that list is read. Names and types come from the set; a
default may be overridden where it is used. A klammer application in a
parameter list is now a definition-time error.
The SKS gains the sets caption_args and hpos_args (:hpos and :offset), and
@table, @image, @image_grid, @reference and @show gain .k declarations. A
distance is no longer written as a position: :hpos 4em is rejected, and the
same layout is :hpos left :offset 4em. Code listings are numbered by
default, like tables and figures.
New engine sources mac/option_set{,_registry}.{h,cpp}; tst/ ships two more
suites, option_set_test.sh and signature_test.sh (twelve in all).
(from dev 34e536cb0329)
2026-08-06 13:11:37 +02:00
|
|
|
$source" -t fix -d 2>&1)
|
|
|
|
|
status=$?
|
|
|
|
|
if [ $status -eq 0 ]; then
|
|
|
|
|
echo "${red}FAIL${reset} $name — expected an error, ktext exited 0"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
if printf '%s' "$output" | tr '\n' ' ' | grep -qF "$needle"; then
|
|
|
|
|
echo "${green}PASS${reset} $name"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} $name"
|
|
|
|
|
echo " expected error containing: [$needle]"
|
|
|
|
|
echo " got: $(printf '%s' "$output" | tr '\n' ' ' | head -c 300)"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# check_warns NAME SUBSTRING SOURCE — SOURCE must be accepted, and its
|
|
|
|
|
# combined output must contain SUBSTRING (used where a warning is expected
|
|
|
|
|
# beside the result, so an exact comparison would test the warning's wording).
|
An output policy for the three commands, and @cond as a true special form
A snapshot of the development tree. The substantial changes since the last one:
COMMAND OUTPUT POLICY. The three commands display text in exactly three cases,
and each owns a stream: LOGGING under "-v" greater than 0 and an ERROR before
termination go to STDERR; OUTPUT THE USER ASKED FOR goes to STDOUT. For ktext
that output is a document, so "ktext doc.kt -d | ..." is now safe -- logging
used to share the stream and land inside the document. A bare command prints
its usage and succeeds rather than failing. Colour is emitted only to a
terminal, per stream, and NO_COLOR is honoured.
"-v 1" reports every decision whose outcome you could not have read off your own
input: the klammerset that was loaded and from which file, a font's directory, a
":files" name's file, how "-o" was expanded. Higher levels are the trace.
The commands no longer warn and continue: an anomaly is an error, described with
its location. Two exceptions remain, each for a stated reason -- a condition
that is expected and temporary by design, and a judgment that is a heuristic
rather than exact.
@cond IS NOW A TRUE SPECIAL FORM, resolved at APPLICATION time rather than when
the file is read. Two consequences for a writer:
* a state variable reaches the predicate. "@@@state Flag :value true @@@
@cond *Flag* | T | F @" renders "T"; it used to see the literal "*Flag*" and
silently take the false branch. The document now behaves like a klammer
body, whose arguments are bound before its conditionals are decided.
* nothing in a discarded branch happens -- it is not read, not evaluated, not
expanded. An @eval in the branch not taken used to run anyway.
Its predicate relation is total and strict: true, True, 1; false, False, 0, and
empty; anything else is an error at the @cond rather than silently false.
@eval REACHING OUTSIDE. ":shell" and ":haskell" now keep the command's standard
error out of the document (it appears under "-v 1") and treat a nonzero exit as
an error naming what the command reported. A command that exits nonzero on
purpose -- "grep" finding no match -- says so with "|| true".
KLAMMER SETS. Several combine: "--klammersets a b c" loads all three in the
order given, sharing one namespace, with the definition modes deciding
collisions. "none" means none and may not be combined with other symbols. A
klammerset with symbol X is declared in a file X/X.k, which is what lets two
sets require the same third set without loading it twice.
TESTS. Four new suites: the kdiag command's interface, the @eval primitive's
contract with the outside world, and verbosity at both tiers. Three suites
that could not run on macOS at all now do.
Assembled from dev commit 6c8ee6c22fca.
2026-08-16 01:37:59 +02:00
|
|
|
# Since 2026-08-15 the override notice is reported at "-v 1" rather than
|
|
|
|
|
# warned about: ":::" exists to override, so the notice fired on the sanctioned
|
|
|
|
|
# use of a feature (see tst/deftype_test.sh's check_warn for the reasoning).
|
|
|
|
|
# The default run must be SILENT and the notice must appear at "-v 1".
|
Option sets: a .o target for shared parameters
A named group of optional parameters, declared once and used by several
klammers, so a writer learns one vocabulary instead of a spelling per
klammer. The "o" target is a pseudo-target beside "k": "k" declares a
klammer's interface and documents it, "o" declares an option interface and
documents it, and neither produces output for any target.
@@caption_args.o :caption :number.bool true :caption_side.side
: Arguments that define a caption for a block element @@
@@code.k :filename @hpos_args :hpos left @ @caption_args :caption_side top @
| text.literal : A source file displayed verbatim @@
A set is used only in the parameter list of a ".k" declaration -- the one
place a klammer's interface is declared once for all of its targets -- and
is resolved as that list is read. Names and types come from the set; a
default may be overridden where it is used. A klammer application in a
parameter list is now a definition-time error.
The SKS gains the sets caption_args and hpos_args (:hpos and :offset), and
@table, @image, @image_grid, @reference and @show gain .k declarations. A
distance is no longer written as a position: :hpos 4em is rejected, and the
same layout is :hpos left :offset 4em. Code listings are numbered by
default, like tables and figures.
New engine sources mac/option_set{,_registry}.{h,cpp}; tst/ ships two more
suites, option_set_test.sh and signature_test.sh (twelve in all).
(from dev 34e536cb0329)
2026-08-06 13:11:37 +02:00
|
|
|
check_warns() {
|
|
|
|
|
local name="$1" needle="$2" source="$3"
|
An output policy for the three commands, and @cond as a true special form
A snapshot of the development tree. The substantial changes since the last one:
COMMAND OUTPUT POLICY. The three commands display text in exactly three cases,
and each owns a stream: LOGGING under "-v" greater than 0 and an ERROR before
termination go to STDERR; OUTPUT THE USER ASKED FOR goes to STDOUT. For ktext
that output is a document, so "ktext doc.kt -d | ..." is now safe -- logging
used to share the stream and land inside the document. A bare command prints
its usage and succeeds rather than failing. Colour is emitted only to a
terminal, per stream, and NO_COLOR is honoured.
"-v 1" reports every decision whose outcome you could not have read off your own
input: the klammerset that was loaded and from which file, a font's directory, a
":files" name's file, how "-o" was expanded. Higher levels are the trace.
The commands no longer warn and continue: an anomaly is an error, described with
its location. Two exceptions remain, each for a stated reason -- a condition
that is expected and temporary by design, and a judgment that is a heuristic
rather than exact.
@cond IS NOW A TRUE SPECIAL FORM, resolved at APPLICATION time rather than when
the file is read. Two consequences for a writer:
* a state variable reaches the predicate. "@@@state Flag :value true @@@
@cond *Flag* | T | F @" renders "T"; it used to see the literal "*Flag*" and
silently take the false branch. The document now behaves like a klammer
body, whose arguments are bound before its conditionals are decided.
* nothing in a discarded branch happens -- it is not read, not evaluated, not
expanded. An @eval in the branch not taken used to run anyway.
Its predicate relation is total and strict: true, True, 1; false, False, 0, and
empty; anything else is an error at the @cond rather than silently false.
@eval REACHING OUTSIDE. ":shell" and ":haskell" now keep the command's standard
error out of the document (it appears under "-v 1") and treat a nonzero exit as
an error naming what the command reported. A command that exits nonzero on
purpose -- "grep" finding no match -- says so with "|| true".
KLAMMER SETS. Several combine: "--klammersets a b c" loads all three in the
order given, sharing one namespace, with the definition modes deciding
collisions. "none" means none and may not be combined with other symbols. A
klammerset with symbol X is declared in a file X/X.k, which is what lets two
sets require the same third set without loading it twice.
TESTS. Four new suites: the kdiag command's interface, the @eval primitive's
contract with the outside world, and verbosity at both tiers. Three suites
that could not run on macOS at all now do.
Assembled from dev commit 6c8ee6c22fca.
2026-08-16 01:37:59 +02:00
|
|
|
local output status quiet
|
|
|
|
|
quiet=$("$KTEXT" --klammersets none -s "$PRELUDE
|
|
|
|
|
$source" -t fix -d 2>&1 >/dev/null)
|
|
|
|
|
if [ -n "$quiet" ]; then
|
|
|
|
|
echo "${red}FAIL${reset} $name — the default run was not silent"
|
|
|
|
|
echo " got: $(printf '%s' "$quiet" | head -1)"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
output=$("$KTEXT" --klammersets none -s "$PRELUDE
|
|
|
|
|
$source" -t fix -d -v 1 2>&1)
|
Option sets: a .o target for shared parameters
A named group of optional parameters, declared once and used by several
klammers, so a writer learns one vocabulary instead of a spelling per
klammer. The "o" target is a pseudo-target beside "k": "k" declares a
klammer's interface and documents it, "o" declares an option interface and
documents it, and neither produces output for any target.
@@caption_args.o :caption :number.bool true :caption_side.side
: Arguments that define a caption for a block element @@
@@code.k :filename @hpos_args :hpos left @ @caption_args :caption_side top @
| text.literal : A source file displayed verbatim @@
A set is used only in the parameter list of a ".k" declaration -- the one
place a klammer's interface is declared once for all of its targets -- and
is resolved as that list is read. Names and types come from the set; a
default may be overridden where it is used. A klammer application in a
parameter list is now a definition-time error.
The SKS gains the sets caption_args and hpos_args (:hpos and :offset), and
@table, @image, @image_grid, @reference and @show gain .k declarations. A
distance is no longer written as a position: :hpos 4em is rejected, and the
same layout is :hpos left :offset 4em. Code listings are numbered by
default, like tables and figures.
New engine sources mac/option_set{,_registry}.{h,cpp}; tst/ ships two more
suites, option_set_test.sh and signature_test.sh (twelve in all).
(from dev 34e536cb0329)
2026-08-06 13:11:37 +02:00
|
|
|
status=$?
|
|
|
|
|
if [ $status -ne 0 ]; then
|
|
|
|
|
echo "${red}FAIL${reset} $name — ktext exited $status"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
if printf '%s' "$output" | tr '\n' ' ' | grep -qF "$needle"; then
|
|
|
|
|
echo "${green}PASS${reset} $name"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} $name"
|
|
|
|
|
echo " expected a warning containing: [$needle]"
|
|
|
|
|
echo " got: $(printf '%s' "$output" | tr '\n' ' ' | head -c 300)"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
echo "${bold}Option set (.o) tests${reset}"
|
|
|
|
|
echo "====================="
|
|
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
# --- The members become the klammer's parameters --------------------------
|
|
|
|
|
|
|
|
|
|
# A declaration using a set accepts the set's options, and the writer's
|
|
|
|
|
# arguments reach the body under the names the set declares.
|
|
|
|
|
check_eq " 1. a set's parameters are the klammer's" \
|
|
|
|
|
"[A|top]" \
|
|
|
|
|
'@@e.k x @cap@ : an element @@
|
|
|
|
|
@@e.fix :: [*caption*|*side*] @@
|
|
|
|
|
@e X :caption A :side top @'
|
|
|
|
|
|
|
|
|
|
# Absent argument, declared default: the set supplies it.
|
|
|
|
|
check_eq " 2. a member's default applies when the argument is absent" \
|
|
|
|
|
"[|true|bottom]" \
|
|
|
|
|
'@@e.k x @cap@ : an element @@
|
|
|
|
|
@@e.fix :: [*caption*|*number*|*side*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
# The use site may override a default -- and only the default.
|
|
|
|
|
check_eq " 3. a use-site override changes the default" \
|
|
|
|
|
"[|true|top]" \
|
|
|
|
|
'@@e.k x @cap :side top @ : an element @@
|
|
|
|
|
@@e.fix :: [*caption*|*number*|*side*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
check_eq " 4. a boolean default can be overridden to false" \
|
|
|
|
|
"[false]" \
|
|
|
|
|
'@@e.k x @cap :number false @ : an element @@
|
|
|
|
|
@@e.fix :: [*number*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
# An option written alone at the use site takes the argument type's :alone
|
|
|
|
|
# value, exactly as it does where an argument is written.
|
|
|
|
|
check_eq " 5. an override written alone takes the argtype's alone value" \
|
|
|
|
|
"[true]" \
|
|
|
|
|
'@@n.o :number.bool false : A number @@
|
|
|
|
|
@@e.k x @n :number @ : an element @@
|
|
|
|
|
@@e.fix :: [*number*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
# Three levels: argument type, option set, use site -- and the writer's
|
|
|
|
|
# argument still wins over all of them.
|
|
|
|
|
check_eq " 6. a written argument wins over the overridden default" \
|
|
|
|
|
"[maybe]" \
|
|
|
|
|
'@@e.k x @cap :side top @ : an element @@
|
|
|
|
|
@@e.fix :: [*side*] @@
|
|
|
|
|
@e X :side maybe @'
|
|
|
|
|
|
|
|
|
|
check_eq " 7. two sets in one declaration" \
|
|
|
|
|
"[bottom|left]" \
|
|
|
|
|
'@@e.k x @cap@ @pos@ : an element @@
|
|
|
|
|
@@e.fix :: [*side*|*hpos*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
check_eq " 8. a set's parameters mix with the klammer's own" \
|
|
|
|
|
"[own|bottom]" \
|
|
|
|
|
'@@e.k x :mine own @cap@ : an element @@
|
|
|
|
|
@@e.fix :: [*mine*|*side*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
# Every target definition is an instance, so all of them get the expanded
|
|
|
|
|
# list: the set is resolved once, in the declaration.
|
|
|
|
|
check_eq " 9. a second target's instance inherits the same parameters" \
|
|
|
|
|
"<bottom>" \
|
|
|
|
|
'@@@target fix2 | another fixture target @@@
|
|
|
|
|
@@e.k x @cap@ : an element @@
|
|
|
|
|
@@e.fix :: [*side*] @@
|
|
|
|
|
@@e.fix2 :: <*side*> @@
|
|
|
|
|
@e X @' \
|
|
|
|
|
fix2
|
|
|
|
|
|
|
|
|
|
# --- The declaration is not a klammer -------------------------------------
|
|
|
|
|
|
|
|
|
|
check_fails "10. a set defines no klammer" \
|
|
|
|
|
'The klammer "cap" is not defined' \
|
|
|
|
|
'@cap@'
|
|
|
|
|
|
|
|
|
|
# --- Where a set may be used ----------------------------------------------
|
|
|
|
|
|
|
|
|
|
check_fails "11. not in a per-target definition" \
|
|
|
|
|
'may be used only in the parameter list of a ".k" declaration' \
|
|
|
|
|
'@@e.fix x @cap@ : [*caption*] @@'
|
|
|
|
|
|
|
|
|
|
check_fails "12. not in a general definition" \
|
|
|
|
|
'may be used only in the parameter list of a ".k" declaration' \
|
|
|
|
|
'@@e x @cap@ : [*caption*] @@'
|
|
|
|
|
|
|
|
|
|
check_fails "13. not in another set" \
|
|
|
|
|
'a set does not include another set' \
|
|
|
|
|
'@@both.o :extra @cap@ : two vocabularies @@'
|
|
|
|
|
|
|
|
|
|
# --- A klammer application in a parameter list ----------------------------
|
|
|
|
|
|
|
|
|
|
check_fails "14. a klammer application in a parameter list is rejected" \
|
|
|
|
|
'A klammer application in a parameter list is not allowed' \
|
|
|
|
|
'@@c : :spliced @@
|
|
|
|
|
@@e.k x @c@ : an element @@'
|
|
|
|
|
|
|
|
|
|
check_fails "15. ... and the message names the declared sets" \
|
|
|
|
|
'Declared option sets: cap, pos' \
|
|
|
|
|
'@@e.k x @nosuch@ : an element @@'
|
|
|
|
|
|
|
|
|
|
# --- Use-site overrides ---------------------------------------------------
|
|
|
|
|
|
|
|
|
|
check_fails "16. an override must name a member of the set" \
|
|
|
|
|
'The option set "cap" has no parameter ":nope"' \
|
|
|
|
|
'@@e.k x @cap :nope 1 @ : an element @@'
|
|
|
|
|
|
|
|
|
|
check_fails "17. an override value is validated at definition time" \
|
|
|
|
|
'does not match the "bool" argument type' \
|
|
|
|
|
'@@e.k x @cap :number perhaps @ : an element @@'
|
|
|
|
|
|
|
|
|
|
check_fails "18. an override may not restate the type" \
|
|
|
|
|
'only a default may be given where it is used' \
|
|
|
|
|
'@@e.k x @cap :number.bool false @ : an element @@'
|
|
|
|
|
|
|
|
|
|
check_fails "19. an override may not give a positional value" \
|
|
|
|
|
'gives a value that is not an option' \
|
|
|
|
|
'@@e.k x @cap here @ : an element @@'
|
|
|
|
|
|
|
|
|
|
# --- What a set may declare -----------------------------------------------
|
|
|
|
|
|
|
|
|
|
check_fails "20. a positional parameter is rejected" \
|
|
|
|
|
'An option set declares only optional parameters' \
|
|
|
|
|
'@@bad.o p :q : oops @@'
|
|
|
|
|
|
|
|
|
|
check_fails "21. a rest parameter is rejected" \
|
|
|
|
|
'An option set declares only optional parameters' \
|
|
|
|
|
'@@bad.o r.rest :q : oops @@'
|
|
|
|
|
|
|
|
|
|
check_fails "22. a set with no parameters is rejected" \
|
|
|
|
|
'declares no parameters' \
|
|
|
|
|
'@@bad.o : nothing at all @@'
|
|
|
|
|
|
|
|
|
|
check_fails '23. "::" has no meaning for a set' \
|
|
|
|
|
'An option set IS a declaration' \
|
|
|
|
|
'@@cap.o :: nope @@'
|
|
|
|
|
|
|
|
|
|
# --- Collisions -----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
check_fails "24. two sets declaring the same name name both sets" \
|
|
|
|
|
'from the option set "cap"' \
|
|
|
|
|
'@@other.o :side right : another side @@
|
|
|
|
|
@@e.k x @cap@ @other@ : an element @@'
|
|
|
|
|
|
|
|
|
|
check_fails "25. a set colliding with a declared parameter" \
|
|
|
|
|
'declared in the parameter list' \
|
|
|
|
|
'@@e.k x :side own @cap@ : an element @@'
|
|
|
|
|
|
|
|
|
|
# --- Redefinition ---------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
check_fails "26. declaring a set twice is an error" \
|
|
|
|
|
'Option set "cap.o" already defined' \
|
|
|
|
|
'@@cap.o :caption : a second caption @@'
|
|
|
|
|
|
|
|
|
|
# A set is its own declaration, so an override restates what it declares --
|
|
|
|
|
# there is no ".k" for it to inherit a parameter list from.
|
|
|
|
|
check_warns '27. ":::" overrides a set, with a warning' \
|
|
|
|
|
'overridden' \
|
|
|
|
|
'@@cap.o :caption :number.bool true :side top ::: a replaced caption @@'
|
|
|
|
|
|
|
|
|
|
check_warns "28. ... and the overriding declaration is what a klammer gets" \
|
|
|
|
|
"[top]" \
|
|
|
|
|
'@@cap.o :caption :number.bool true :side top ::: a replaced caption @@
|
|
|
|
|
@@e.k x @cap@ : an element @@
|
|
|
|
|
@@e.fix :: [*side*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
# A "::::" default is silently superseded by a later create, and the create
|
|
|
|
|
# is what the using declaration gets.
|
|
|
|
|
check_eq "29. a default set is superseded by a later declaration" \
|
|
|
|
|
"[right]" \
|
|
|
|
|
'@@d.o :where left :::: a default @@
|
|
|
|
|
@@d.o :where right : the real one @@
|
|
|
|
|
@@e.k x @d@ : an element @@
|
|
|
|
|
@@e.fix :: [*where*] @@
|
|
|
|
|
@e X @'
|
|
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
echo "====================="
|
|
|
|
|
echo "Results: ${green}$PASS passed${reset}, ${red}$FAIL failed${reset}"
|
|
|
|
|
[ $FAIL -eq 0 ]
|