Skip to content

io: name the parameter, the material and the entry when a deck is wrong (#66, #67) - #85

Merged
petlenz merged 1 commit into
mainfrom
fix/parameter-diagnostics
Oct 19, 2026
Merged

petlenz merged 1 commit into
mainfrom
fix/parameter-diagnostics

Conversation

@petlenz

@petlenz petlenz commented Sep 20, 2026 •

Copy link
Copy Markdown
Member

Closes #66, #67, #148, #149 (the two rows of #65 fixed here; #65 stays open for its remaining sub-issues #150–#153).

Three failures that named nothing useful.

A wrong parameter type was a bare bad_any_cast (#65)

get_parameter() let std::bad_any_cast escape: no parameter, no material, no type, and not a class a caller would think to catch. Writing 1 where 1.0 is read -- an int for a double, which both JSON and C++ make easy -- produced bad any_cast and nothing else, at construction, before the material could say anything about itself.

set_parameter() already wrapped this. get, which every material calls several times, did not.

One reader served two different parameters (#66)

The JSON reader registry is keyed on std::type_index alone. block_ref is std::pair<std::string, std::string>, so vector_newton's zero_blocks and weighted_sum's terms are the same C++ type and resolve to the same reader. A malformed weighted_sum term reported

zero_blocks: each entry must be a [row, column] pair

naming a parameter of a different material.

Readers now receive the parameter key -- it was already available at the read() call site and thrown away -- so the shared reader names whatever it was actually given. add_for_key() lets one parameter keep its own wording without disturbing the other user of the type, so zero_blocks still says [row, column].

Any future pair of parameters sharing a C++ type would have hit the same thing.

"type" errors were a dead end (#67)

A missing "type" surfaced nlohmann's own key 'type' not found, from a library the user never named, with no indication of which entry was at fault. A misspelt one echoed the name back with no candidates.

Both now name the entry by its "name", and an unknown type suggests the nearest registered one (j2_plasticty -> j2_plasticity) or lists them all when nothing is close.

Not fixed here

The remaining rows of #65 are its sub-issues: unknown optional keys in the C++ path (#150), non-integral values for integer parameters (#151), check_data_type through the declaration helpers (#152), all missing names in the exception text (#153, handler side numsim-core#20).

@petlenz

petlenz commented Oct 17, 2026

Copy link
Copy Markdown
Member Author

Review findings (design, tmech expressions instead of component loops, modern C++, comments, tests, correctness). Severity: must = wrong result, hang, build break or unreachable feature; should = design, duplication, accuracy; nit = style.

parameter diagnostics — needs changes

  • [should] wrapper catches only bad_any_cast; numsim-core's missing-key invalid_argument still names no material; rvalue overload now a copying duplicate → delete; message names neither expected nor stored type; where attached only to the two "type" checks (reader failures and ctx.create errors arrive without the entry); "name": 3 surfaces nlohmann's type_error; "capped" Levenshtein comment is false; two identical read_name_pairs bodies; <print> drift vs main.

Conflicts and landing order (open PRs on main)

@petlenz

petlenz commented Oct 18, 2026

Copy link
Copy Markdown
Member Author

Rebased on main; the review findings addressed in the commit:

  • get_parameter: one overload (the rvalue one was a copying duplicate); a wrong stored type says what the material reads it as ("is not a real number as this material reads it …"), and a missing key no longer surfaces the handler's "Key K not found" but "material 'x': parameter 'K' is missing".
  • create_from_json: the entry (where) is attached to every error — reader failures and the material's own checks included — not only to the two "type" checks; a non-string "name" is reported as such instead of reaching nlohmann first.
  • edit_distance is capped as its comment claimed (stops when a whole row exceeds the cap).
  • Comments cut to one or two lines throughout; the test essays too. Tests added: missing parameter names material and key, the type read is named, a reader failure and a missing required parameter carry the entry, a numeric "name".

The read_name_pairs duplicate and the <print> drift are not in the rebased diff any more.

The diagnostics, set_parameter and json_model suites pass locally (g++-14); the full run follows in CI.

@petlenz
petlenz force-pushed the fix/parameter-diagnostics branch from 64cfe18 to 0920a07 Compare October 18, 2026 20:16
…ng (#65, #66, #67)

Three failures that named nothing useful.

A wrong parameter type threw a bare std::bad_any_cast out of
get_parameter(): no parameter, no material, no type, and not a class a
caller would think to catch. Writing 1 where 1.0 is read -- an int for a
double, which both JSON and C++ make easy -- produced "bad any_cast" and
nothing else, at construction, before the material could say anything
about itself. set_parameter() already wrapped this; get, which every
material calls several times, did not.

The JSON reader registry is keyed on std::type_index alone, and block_ref
is std::pair<std::string, std::string>, so vector_newton's "zero_blocks"
and weighted_sum's "terms" are the SAME C++ type and share one reader. A
malformed weighted_sum term therefore reported

    zero_blocks: each entry must be a [row, column] pair

naming a parameter of a different material. Readers now receive the
parameter key -- it was already available at the read() call site and
thrown away -- so the shared reader names whatever it was actually given,
and add_for_key() lets one parameter keep its own wording without
disturbing the other user of the type. Any future pair of parameters
sharing a C++ type would have hit the same thing.

A missing "type" surfaced nlohmann's own "key 'type' not found", from a
library the user never named, with no indication of which entry was at
fault. A misspelt one echoed the name back with no candidates. Both now
name the entry by its "name", and an unknown type suggests the nearest
registered one or lists them all when nothing is close.

Not fixed here: a misspelt OPTIONAL key is still ignored silently in the
C++ path. parameter_handler exposes no way to enumerate its keys, only
find() and print(), so comparing a handler against a schema needs a
numsim-core change. #65 stays open for that half.

310/310. Mutation tested: each check reverted in turn fails only its own
tests. get_parameter is overloaded on how the key arrives and materials
use both -- a string literal binds to the rvalue overload, a stored
std::string to the const-reference one -- and the first version of the
test reached only one, leaving the other's guard free to delete with the
suite still green.
@petlenz

petlenz commented Oct 18, 2026

Copy link
Copy Markdown
Member Author

Follow-up push: the loops of the PR are std algorithms now — suggest_type uses std::ranges::min_element with the edit distance as projection, std::ranges::sort and std::accumulate; the two block_ref readers share one string_pairs helper built on std::ranges::transform (the last duplicated body). Full local run before this push: 682/682; the four affected suites pass after it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JSON reader registry is keyed on type_index, so parameters of the same C++ type share a reader and its error text

1 participant