From c16171fd6ccc9d4b8bd5ae7ed7d8803674042c26 Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sun, 27 Jul 2025 21:38:34 -0700 Subject: [PATCH 1/7] doc(README): update ifx command to remove -coarray It appears that Intel has dropped the requirement for the -coarray flag for code that uses multi-image features. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 271ffe982..ad91a849c 100644 --- a/README.md +++ b/README.md @@ -234,7 +234,7 @@ Compiler | Version(s) Tested | Known Issues LLVM `flang-new` | 19, 20 | none NAG `nagfor` | 7.2 Build 7227 | none GCC `gfortran` | 13, 14, 15 | see 1 below -Intel `ifx` | 2025.4 Build 20241205 | see 2 below +Intel `ifx` | 2025.1.1 Build 20250418 | see 2 below 1. `gfortran` issues: - With GCC 14 or earlier, the `test_description_t` constructor's @@ -287,8 +287,9 @@ where the `-ffree-line-length-none` turns on support for lines exceeding the For #### Intel (`ifx`) compiler ``` -fpm test --compiler ifx --flag "-fpp -O3 -coarray" --profile release +fpm test --compiler ifx --flag "-fpp -O3" --profile release ``` +Older versions of `ifx` might require adding `-coarray` to the quoted argument just after `--flag` above. Documentation ------------- From 142d776f8f247016c6d6642a11f85f5792975b4d Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sun, 27 Jul 2025 22:10:43 -0700 Subject: [PATCH 2/7] fix(formats_m): replace G0 w/G25.20 in CSV formats This commit fixes an issue that caused one failing test with ifx. --- src/julienne/julienne_formats_m.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/julienne/julienne_formats_m.F90 b/src/julienne/julienne_formats_m.F90 index 471da85ac..386b8d08f 100644 --- a/src/julienne/julienne_formats_m.F90 +++ b/src/julienne/julienne_formats_m.F90 @@ -4,8 +4,8 @@ module julienne_formats_m !! Useful strings for formatting `print` and `write` statements implicit none - character(len=*), parameter :: csv = "(*(G0,:,','))" !! comma-separated values - character(len=*), parameter :: cscv = "(*('(',G0,',',G0,')',:,',')))" !! comma-separated complex values + character(len=*), parameter :: csv = "(*(G25.20,:,','))" !! comma-separated values + character(len=*), parameter :: cscv = "(*('(',G25.20,',',G25.20,')',:,',')))" !! comma-separated complex values #ifndef _CRAYFTN From cf22595613a3a7a48a9e6e7d48b79ee7333f4e4f Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sun, 27 Jul 2025 22:28:36 -0700 Subject: [PATCH 3/7] fix(formats_m): mk CSV dble formats work with ifx --- src/julienne/julienne_formats_s.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/julienne/julienne_formats_s.F90 b/src/julienne/julienne_formats_s.F90 index 20de00956..62adb6680 100644 --- a/src/julienne/julienne_formats_s.F90 +++ b/src/julienne/julienne_formats_s.F90 @@ -10,8 +10,9 @@ module procedure separated_values character(len=*), parameter :: prefix = "(*(G0,:,'" - character(len=*), parameter :: suffix = "'))" + character(len=*), parameter :: double_prefix = "(*(G25.20,:,'" character(len=*), parameter :: complex_prefix = "(*('(',G0,',',G0,')',:,'" + character(len=*), parameter :: suffix = "'))" select rank(mold) rank(1) @@ -19,7 +20,7 @@ type is(complex) format_string = complex_prefix // separator // suffix type is(double precision) - format_string = prefix // separator // suffix + format_string = double_prefix // separator // "'))" type is(real) format_string = prefix // separator // suffix type is(integer) From 4c96b8598c1b18d65886f9ab6ed2ca7807628292 Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sun, 27 Jul 2025 22:29:40 -0700 Subject: [PATCH 4/7] fix(formats_test): use character mold for char CSV --- test/modules/formats_test_m.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/modules/formats_test_m.F90 b/test/modules/formats_test_m.F90 index 4e86ded29..6ca6f87ea 100644 --- a/test/modules/formats_test_m.F90 +++ b/test/modules/formats_test_m.F90 @@ -147,7 +147,7 @@ function check_csv_character() result(test_diagnosis) character(len=200) captured_output character(len=*), parameter :: expected_output = "Yodel, Ay, Hee, Hoo!" - write(captured_output, fmt = separated_values(separator=", ", mold=[integer::])) "Yodel", "Ay", "Hee", "Hoo!" + write(captured_output, fmt = separated_values(separator=", ", mold=[character::])) "Yodel", "Ay", "Hee", "Hoo!" test_diagnosis = test_diagnosis_t( & test_passed = expected_output == captured_output & From 5048c3d48ea2e4bdec774ad48d6d02a5809785d2 Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sun, 3 Aug 2025 18:39:22 -0700 Subject: [PATCH 5/7] refac(string_test): fix typo, combine ptr decl/def --- test/modules/string_test_m.F90 | 92 ++++++++++++---------------------- 1 file changed, 31 insertions(+), 61 deletions(-) diff --git a/test/modules/string_test_m.F90 b/test/modules/string_test_m.F90 index 7b693e2cc..28de67e3b 100644 --- a/test/modules/string_test_m.F90 +++ b/test/modules/string_test_m.F90 @@ -49,7 +49,7 @@ function results() result(test_results) ,test_description_t("extracting a key string from a colon-separated key/value pair", extracts_key)& ,test_description_t("extracting double-precision value from colon-separated key/value pair", extracts_double_precision_value)& ,test_description_t("extracting a real value from a colon-separated key/value pair", extracts_real_value)& - ,test_description_t("extracting a string value from a colon-separated key/value pair", extracts_character_value)& + ,test_description_t("extracting a character value from a colon-separated key/value pair", extracts_character_value)& ,test_description_t("extracting a string value from a colon-separated key/value pair", extracts_string_value)& ,test_description_t("extracting an integer value from a colon-separated key/value pair", extracts_integer_value)& ,test_description_t("extracting a logical value from a colon-separated key/value pair", extracts_logical_value)& @@ -78,72 +78,42 @@ function results() result(test_results) #else ! Work around missing Fortran 2008 feature: associating a procedure actual argument with a procedure pointer dummy argument: procedure(diagnosis_function_i), pointer :: & - check_allocation_ptr & - ,extracts_key_ptr & - ,extracts_double_precision_value_ptr & - ,extracts_real_value_ptr & - ,extracts_character_value_ptr & - ,extracts_string_value_ptr & - ,extracts_integer_value_ptr & - ,extracts_logical_value_ptr & - ,extracts_integer_array_value_ptr & - ,extracts_real_array_value_ptr & - ,extracts_dp_array_value_ptr & - ,supports_equivalence_operator_ptr & - ,supports_non_equivalence_operator_ptr & - ,assigns_string_t_to_character_ptr & - ,assigns_character_to_string_t_ptr & - ,supports_concatenation_operator_ptr & - ,constructs_from_default_integer_ptr & - ,constructs_from_default_real_ptr & - ,constructs_from_double_precision_ptr & - ,constructs_from_default_complex_ptr & - ,constructs_from_default_logical_ptr & - ,constructs_from_logical_c_bool_ptr & - ,extracts_file_base_name_ptr & - ,extracts_file_name_extension_ptr & - ,concatenates_elements_ptr & - ,brackets_strings_ptr & - ,extracts_string_array_value_ptr & - ,constructs_separated_values_ptr & - ,constructs_from_double_precision_complex_ptr - - check_allocation_ptr => check_allocation - extracts_key_ptr => extracts_key - extracts_double_precision_value_ptr => extracts_double_precision_value - extracts_real_value_ptr => extracts_real_value - extracts_character_value_ptr => extracts_character_value - extracts_string_value_ptr => extracts_string_value - extracts_integer_value_ptr => extracts_integer_value - extracts_logical_value_ptr => extracts_logical_value - extracts_integer_array_value_ptr => extracts_integer_array_value - extracts_real_array_value_ptr => extracts_real_array_value - extracts_dp_array_value_ptr => extracts_dp_array_value - supports_equivalence_operator_ptr => supports_equivalence_operator - supports_non_equivalence_operator_ptr => supports_non_equivalence_operator - assigns_string_t_to_character_ptr => assigns_string_t_to_character - assigns_character_to_string_t_ptr => assigns_character_to_string_t - supports_concatenation_operator_ptr => supports_concatenation_operator - constructs_from_default_integer_ptr => constructs_from_default_integer - constructs_from_default_real_ptr => constructs_from_default_real - constructs_from_double_precision_ptr => constructs_from_double_precision - constructs_from_default_complex_ptr => constructs_from_default_complex - constructs_from_default_logical_ptr => constructs_from_default_logical - constructs_from_logical_c_bool_ptr => constructs_from_logical_c_bool - extracts_file_base_name_ptr => extracts_file_base_name - extracts_file_name_extension_ptr => extracts_file_name_extension - concatenates_elements_ptr => concatenates_elements - brackets_strings_ptr => brackets_strings - extracts_string_array_value_ptr => extracts_string_array_value - constructs_separated_values_ptr => constructs_separated_values - constructs_from_double_precision_complex_ptr => constructs_from_double_precision_complex + ,check_allocation_ptr => check_allocation & + ,extracts_key_ptr => extracts_key & + ,extracts_double_precision_value_ptr => extracts_double_precision_value & + ,extracts_real_value_ptr => extracts_real_value & + ,extracts_character_value_ptr => extracts_character_value & + ,extracts_string_value_ptr => extracts_string_value & + ,extracts_integer_value_ptr => extracts_integer_value & + ,extracts_logical_value_ptr => extracts_logical_value & + ,extracts_integer_array_value_ptr => extracts_integer_array_value & + ,extracts_real_array_value_ptr => extracts_real_array_value & + ,extracts_dp_array_value_ptr => extracts_dp_array_value & + ,supports_equivalence_operator_ptr => supports_equivalence_operator & + ,supports_non_equivalence_operator_ptr => supports_non_equivalence_operator & + ,assigns_string_t_to_character_ptr => assigns_string_t_to_character & + ,assigns_character_to_string_t_ptr => assigns_character_to_string_t & + ,supports_concatenation_operator_ptr => supports_concatenation_operator & + ,constructs_from_default_integer_ptr => constructs_from_default_integer & + ,constructs_from_default_real_ptr => constructs_from_default_real & + ,constructs_from_double_precision_ptr => constructs_from_double_precision & + ,constructs_from_default_complex_ptr => constructs_from_default_complex & + ,constructs_from_default_logical_ptr => constructs_from_default_logical & + ,constructs_from_logical_c_bool_ptr => constructs_from_logical_c_bool & + ,extracts_file_base_name_ptr => extracts_file_base_name & + ,extracts_file_name_extension_ptr => extracts_file_name_extension & + ,concatenates_elements_ptr => concatenates_elements & + ,brackets_strings_ptr => brackets_strings & + ,extracts_string_array_value_ptr => extracts_string_array_value & + ,constructs_separated_values_ptr => constructs_separated_values & + ,constructs_from_double_precision_complex_ptr => constructs_from_double_precision_complex test_descriptions = [ & test_description_t("is_allocated() result .true. if & only if the string_t component(s) is/are allocated", check_allocation_ptr)& ,test_description_t("extracting a key string from a colon-separated key/value pair", extracts_key_ptr)& ,test_description_t("extracting double-precision value from colon-separated key/value pair", extracts_double_precision_value_ptr)& ,test_description_t("extracting a real value from a colon-separated key/value pair", extracts_real_value_ptr)& - ,test_description_t("extracting a string value from a colon-separated key/value pair", extracts_character_value_ptr)& + ,test_description_t("extracting a character value from a colon-separated key/value pair", extracts_character_value_ptr)& ,test_description_t("extracting a string value from a colon-separated key/value pair", extracts_string_value_ptr)& ,test_description_t("extracting an integer value from a colon-separated key/value pair", extracts_integer_value_ptr)& ,test_description_t("extracting a logical value from a colon-separated key/value pair", extracts_logical_value_ptr)& From a8a6d9b740c4e13c01ee0a42f840aefdb15ef4ea Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sun, 3 Aug 2025 22:30:31 -0500 Subject: [PATCH 6/7] feat(string_t): add get_string_with_character_key This commit adds a specific type-bound procedure for the string_t get_json_value generic binding. This procedure finishes out the possible combinations of a string_t or character key with a string_t or character mold/result-value. --- src/julienne/julienne_string_m.f90 | 21 +++++++++++++++------ src/julienne/julienne_string_s.F90 | 14 ++++++++++---- test/modules/string_test_m.F90 | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/julienne/julienne_string_m.f90 b/src/julienne/julienne_string_m.f90 index 02b8f3b8e..dae16dc33 100644 --- a/src/julienne/julienne_string_m.f90 +++ b/src/julienne/julienne_string_m.f90 @@ -26,22 +26,24 @@ module julienne_string_m generic :: operator(/=) => string_t_ne_string_t, string_t_ne_character, character_ne_string_t generic :: operator(==) => string_t_eq_string_t, string_t_eq_character, character_eq_string_t generic :: assignment(= ) => assign_string_t_to_character, assign_character_to_string_t - generic :: get_json_value => get_string, get_string_t_array_with_character_key, get_string_t_array_with_string_t_key & + generic :: get_json_value => get_string_with_string_key & + ,get_character_with_string_key, get_character_with_character_key & + ,get_string_t_array_with_character_key, get_string_t_array_with_string_t_key & ,get_real, get_real_with_character_key & - ,get_character, get_character_with_character_key & ,get_logical, get_logical_with_character_key & ,get_real_array ,get_real_array_with_character_key & ,get_integer_array, get_integer_array_with_character_key & ,get_integer, get_integer_with_character_key & ,get_double_precision, get_double_precision_with_character_key & ,get_double_precision_array, get_double_precision_array_with_character_key + procedure, private :: get_string_with_string_key + procedure, private :: get_character_with_string_key, get_character_with_character_key + procedure, private :: get_string_t_array_with_character_key, get_string_t_array_with_string_t_key procedure, private :: get_real, get_real_with_character_key - procedure, private :: get_string, get_string_t_array_with_character_key, get_string_t_array_with_string_t_key procedure, private :: get_logical, get_logical_with_character_key procedure, private :: get_integer, get_integer_with_character_key procedure, private :: get_real_array, get_real_array_with_character_key procedure, private :: get_integer_array, get_integer_array_with_character_key - procedure, private :: get_character, get_character_with_character_key procedure, private :: get_double_precision, get_double_precision_with_character_key procedure, private :: get_double_precision_array, get_double_precision_array_with_character_key procedure, private :: string_t_ne_string_t, string_t_ne_character @@ -250,7 +252,7 @@ pure module function get_double_precision_array_with_character_key(self, key, mo double precision, allocatable :: value_(:) end function - pure module function get_character(self, key, mold) result(value_) + pure module function get_character_with_string_key(self, key, mold) result(value_) implicit none class(string_t), intent(in) :: self, key character(len=*), intent(in) :: mold @@ -264,12 +266,19 @@ pure module function get_character_with_character_key(self, key, mold) result(va character(len=:), allocatable :: value_ end function - elemental module function get_string(self, key, mold) result(value_) + elemental module function get_string_with_string_key(self, key, mold) result(value_) implicit none class(string_t), intent(in) :: self, key, mold type(string_t) :: value_ end function + elemental module function get_string_with_character_key(self, key, mold) result(value_) + implicit none + class(string_t), intent(in) :: self, mold + character(len=*), intent(in) :: key + type(string_t) :: value_ + end function + pure module function get_string_t_array_with_string_t_key(self, key, mold) result(value_) implicit none class(string_t), intent(in) :: self diff --git a/src/julienne/julienne_string_s.F90 b/src/julienne/julienne_string_s.F90 index d92b33773..77306e7a5 100644 --- a/src/julienne/julienne_string_s.F90 +++ b/src/julienne/julienne_string_s.F90 @@ -220,14 +220,20 @@ end procedure - module procedure get_character - associate(string_value => self%get_string(key, string_t(mold))) + module procedure get_character_with_string_key + associate(string_value => self%get_string_with_string_key(key, string_t(mold))) value_ = string_value%string() end associate end procedure module procedure get_character_with_character_key - associate(string_value => self%get_string(string_t(key), string_t(mold))) + associate(string_value => self%get_string_with_string_key(string_t(key), string_t(mold))) + value_ = string_value%string() + end associate + end procedure + + module procedure get_string_with_character_key + associate(string_value => self%get_string_with_string_key(string_t(key), mold)) value_ = string_value%string() end associate end procedure @@ -265,7 +271,7 @@ end associate end procedure - module procedure get_string + module procedure get_string_with_string_key character(len=:), allocatable :: raw_line diff --git a/test/modules/string_test_m.F90 b/test/modules/string_test_m.F90 index 28de67e3b..602044e81 100644 --- a/test/modules/string_test_m.F90 +++ b/test/modules/string_test_m.F90 @@ -78,7 +78,7 @@ function results() result(test_results) #else ! Work around missing Fortran 2008 feature: associating a procedure actual argument with a procedure pointer dummy argument: procedure(diagnosis_function_i), pointer :: & - ,check_allocation_ptr => check_allocation & + check_allocation_ptr => check_allocation & ,extracts_key_ptr => extracts_key & ,extracts_double_precision_value_ptr => extracts_double_precision_value & ,extracts_real_value_ptr => extracts_real_value & From 10100ee795fd50576ae1643ccfda7e63d77c797d Mon Sep 17 00:00:00 2001 From: Damian Rouson Date: Sun, 3 Aug 2025 22:57:48 -0500 Subject: [PATCH 7/7] feat(string,test_dia): get_string_with_str, .also. This commit 1. Adds test_diagnosis_t operator(.also.) synonym for .and. 2. Adds specific type-bound procedure get_string_with_character_key corresponding to get_json_value generic binding. --- src/julienne/julienne_string_m.f90 | 6 ++--- src/julienne/julienne_test_diagnosis_m.F90 | 9 +++++-- src/julienne/julienne_test_diagnosis_s.F90 | 2 +- src/julienne_m.f90 | 1 + test/modules/string_test_m.F90 | 30 ++++++++-------------- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/julienne/julienne_string_m.f90 b/src/julienne/julienne_string_m.f90 index dae16dc33..ed5c4a5fb 100644 --- a/src/julienne/julienne_string_m.f90 +++ b/src/julienne/julienne_string_m.f90 @@ -26,7 +26,7 @@ module julienne_string_m generic :: operator(/=) => string_t_ne_string_t, string_t_ne_character, character_ne_string_t generic :: operator(==) => string_t_eq_string_t, string_t_eq_character, character_eq_string_t generic :: assignment(= ) => assign_string_t_to_character, assign_character_to_string_t - generic :: get_json_value => get_string_with_string_key & + generic :: get_json_value => get_string_with_string_key, get_string_with_character_key & ,get_character_with_string_key, get_character_with_character_key & ,get_string_t_array_with_character_key, get_string_t_array_with_string_t_key & ,get_real, get_real_with_character_key & @@ -36,7 +36,7 @@ module julienne_string_m ,get_integer, get_integer_with_character_key & ,get_double_precision, get_double_precision_with_character_key & ,get_double_precision_array, get_double_precision_array_with_character_key - procedure, private :: get_string_with_string_key + procedure, private :: get_string_with_string_key, get_string_with_character_key procedure, private :: get_character_with_string_key, get_character_with_character_key procedure, private :: get_string_t_array_with_character_key, get_string_t_array_with_string_t_key procedure, private :: get_real, get_real_with_character_key @@ -272,7 +272,7 @@ elemental module function get_string_with_string_key(self, key, mold) result(val type(string_t) :: value_ end function - elemental module function get_string_with_character_key(self, key, mold) result(value_) + pure module function get_string_with_character_key(self, key, mold) result(value_) implicit none class(string_t), intent(in) :: self, mold character(len=*), intent(in) :: key diff --git a/src/julienne/julienne_test_diagnosis_m.F90 b/src/julienne/julienne_test_diagnosis_m.F90 index a395ffff1..fe1e7a642 100644 --- a/src/julienne/julienne_test_diagnosis_m.F90 +++ b/src/julienne/julienne_test_diagnosis_m.F90 @@ -15,6 +15,7 @@ module julienne_test_diagnosis_m public :: julienne_assert public :: operator(.all.) public :: operator(.and.) + public :: operator(.also.) public :: operator(.approximates.) public :: operator(.isAtLeast.) public :: operator(.isAtMost.) @@ -181,9 +182,9 @@ pure module function aggregate_rank15_diagnosis(diagnoses) result(diagnosis) #endif end interface - interface operator(.and.) + interface operator(.also.) - elemental module function and(lhs, rhs) result(diagnosis) + elemental module function also(lhs, rhs) result(diagnosis) implicit none type(test_diagnosis_t), intent(in) :: lhs, rhs type(test_diagnosis_t) diagnosis @@ -191,6 +192,10 @@ elemental module function and(lhs, rhs) result(diagnosis) end interface + interface operator(.and.) + module procedure also + end interface + interface operator(.approximates.) elemental module function approximates_real(actual, expected) result(operands) diff --git a/src/julienne/julienne_test_diagnosis_s.F90 b/src/julienne/julienne_test_diagnosis_s.F90 index 7b359d500..249fb974c 100644 --- a/src/julienne/julienne_test_diagnosis_s.F90 +++ b/src/julienne/julienne_test_diagnosis_s.F90 @@ -10,7 +10,7 @@ implicit none contains - module procedure and + module procedure also diagnosis = .all. ([lhs,rhs]) end procedure diff --git a/src/julienne_m.f90 b/src/julienne_m.f90 index 38d36c62a..cd232fa14 100644 --- a/src/julienne_m.f90 +++ b/src/julienne_m.f90 @@ -14,6 +14,7 @@ module julienne_m ,julienne_assert & ,operator(.all.) & ,operator(.and.) & + ,operator(.also.) & ,operator(.approximates.) & ,operator(.equalsExpected.) & ,operator(.isAtLeast.) & diff --git a/test/modules/string_test_m.F90 b/test/modules/string_test_m.F90 index 602044e81..3969a32ad 100644 --- a/test/modules/string_test_m.F90 +++ b/test/modules/string_test_m.F90 @@ -17,6 +17,8 @@ module string_test_m #if ! HAVE_PROCEDURE_ACTUAL_FOR_POINTER_DUMMY ,diagnosis_function_i & #endif + ,operator(.equalsExpected.) & + ,operator(.also.) & ,operator(.cat.) & ,operator(.csv.) & ,operator(.sv.) @@ -209,32 +211,22 @@ function extracts_character_value() result(test_diagnosis) type(test_diagnosis_t) test_diagnosis associate(line => string_t('"foo" : "bar"'), line_with_comma => string_t('"foo" : "bar",')) - associate(json_values => [ & - line%get_json_value(key="foo" , mold="") & - ,line%get_json_value(key=string_t("foo"), mold="") & - ,line_with_comma%get_json_value(key="foo" , mold="") & - ,line_with_comma%get_json_value(key=string_t("foo"), mold="") & - ]) - test_diagnosis = test_diagnosis_t( & - test_passed = all(json_values == "bar") & - ,diagnostics_string = "expected bar; actual " // .csv. json_values & - ) - end associate + test_diagnosis = (line%get_json_value( key= "foo" , mold="") .equalsExpected. "bar") & + .also. (line_with_comma%get_json_value(key= "foo" , mold="") .equalsExpected. "bar") & + .also. (line%get_json_value( key=string_t("foo"), mold="") .equalsExpected. "bar") & + .also. (line_with_comma%get_json_value(key=string_t("foo"), mold="") .equalsExpected. "bar") end associate end function function extracts_string_value() result(test_diagnosis) type(test_diagnosis_t) test_diagnosis - associate(line => string_t('"foo" : "bar"')) - associate(json_value => line%get_json_value(key=string_t("foo"), mold=string_t(""))) - test_diagnosis = test_diagnosis_t( & - test_passed = json_value == "bar", & - diagnostics_string = "expected 'bar', actual " // json_value & - ) - end associate + associate(line => string_t('"foo" : "bar"'), line_with_comma => string_t('"foo" : "bar",')) + test_diagnosis = (line%get_json_value( key= "foo" , mold=string_t("")) .equalsExpected. "bar") & + .also. (line_with_comma%get_json_value(key= "foo" , mold=string_t("")) .equalsExpected. "bar") & + .also. (line%get_json_value( key=string_t("foo"), mold=string_t("")) .equalsExpected. "bar") & + .also. (line_with_comma%get_json_value(key=string_t("foo"), mold=string_t("")) .equalsExpected. "bar") end associate - end function function extracts_integer_value() result(test_diagnosis)