From 966f1e293d98f432d5a44035b459d05eef88f307 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 26 Jun 2026 03:05:57 -0600 Subject: [PATCH] test: add object field CHECK TYPE fixture --- CHANGELOG.md | 5 +++++ docs/ADVANCED_STATIC_TYPING.md | 2 +- docs/CURRENT_STATUS.md | 2 +- docs/ROADMAP.md | 2 +- src/claro.c | 2 +- ...check_object_field_check_type_text_yesno_good.claro | 10 ++++++++++ tools/validate_typecheck_diagnostics.py | 1 + 7 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 tests/typecheck_object_field_check_type_text_yesno_good.claro diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d3b6c9..d3be96c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v1.18.26-dev object field CHECK TYPE TEXT/YESNO validation + +- Added a focused positive `claro typecheck` fixture for direct object-field metadata checks: `CHECK TYPE player.name IS TEXT` and `CHECK TYPE player.ready IS YESNO` after `NEW Player player` and direct field assignments. +- Wired the fixture into both the typecheck diagnostics validator and `claro validate`; no production typechecker change was needed because the existing direct object-field metadata path already accepts these checks. + ## v1.18.26-dev object field unknown YESNO diagnostic validation - Added a focused negative `claro typecheck` fixture for direct object-field assignment to an undeclared field with a YESNO value: `NEW Player player` followed by `SET player.ready YES` when the class only declares `HAS score NUMBER`. diff --git a/docs/ADVANCED_STATIC_TYPING.md b/docs/ADVANCED_STATIC_TYPING.md index 3166949..29069aa 100644 --- a/docs/ADVANCED_STATIC_TYPING.md +++ b/docs/ADVANCED_STATIC_TYPING.md @@ -174,7 +174,7 @@ Object Player has no field nickname. Check the field name or add HAS nickname TE Object Player has no field ready. Check the field name or add HAS ready YESNO to the class. ``` -Both sides of this narrow field foundation are covered by validation: `tests/typecheck_object_field_good.claro` checks that `SET player.score 10` is accepted for a `HAS score NUMBER` field, `tests/typecheck_object_field_text_good.claro` checks that `SET player.name "Ada"` is accepted for a `HAS name TEXT` field, `tests/typecheck_object_field_yesno_good.claro` checks that `SET player.ready YES` is accepted for a `HAS ready YESNO` field, `tests/typecheck_object_field_bad.claro` checks the NUMBER wrong-type diagnostic, `tests/typecheck_object_field_text_bad.claro` checks the TEXT wrong-type diagnostic, `tests/typecheck_object_field_yesno_bad.claro` checks the YESNO wrong-type diagnostic, `tests/typecheck_object_field_unknown_bad.claro` checks a NUMBER-valued unknown-field diagnostic, `tests/typecheck_object_field_unknown_text_bad.claro` checks a TEXT-valued unknown-field diagnostic, and `tests/typecheck_object_field_unknown_yesno_bad.claro` checks a YESNO-valued unknown-field diagnostic. +Both sides of this narrow field foundation are covered by validation: `tests/typecheck_object_field_good.claro` checks that `SET player.score 10` is accepted for a `HAS score NUMBER` field, `tests/typecheck_object_field_text_good.claro` checks that `SET player.name "Ada"` is accepted for a `HAS name TEXT` field, `tests/typecheck_object_field_yesno_good.claro` checks that `SET player.ready YES` is accepted for a `HAS ready YESNO` field, `tests/typecheck_object_field_check_type_text_yesno_good.claro` checks that direct `CHECK TYPE player.name IS TEXT` and `CHECK TYPE player.ready IS YESNO` metadata checks are accepted, `tests/typecheck_object_field_bad.claro` checks the NUMBER wrong-type diagnostic, `tests/typecheck_object_field_text_bad.claro` checks the TEXT wrong-type diagnostic, `tests/typecheck_object_field_yesno_bad.claro` checks the YESNO wrong-type diagnostic, `tests/typecheck_object_field_unknown_bad.claro` checks a NUMBER-valued unknown-field diagnostic, `tests/typecheck_object_field_unknown_text_bad.claro` checks a TEXT-valued unknown-field diagnostic, and `tests/typecheck_object_field_unknown_yesno_bad.claro` checks a YESNO-valued unknown-field diagnostic. This slice is intentionally small: it covers direct `NEW Class object` plus `SET object.field value` cases in one file. Broader object flows, aliases, method return checks, and richer object signatures remain future work. diff --git a/docs/CURRENT_STATUS.md b/docs/CURRENT_STATUS.md index 2781d99..60900ce 100644 --- a/docs/CURRENT_STATUS.md +++ b/docs/CURRENT_STATUS.md @@ -53,7 +53,7 @@ Ready now: - `TYPE OF` and `CHECK TYPE` - typed list/map checks through `claro typecheck` - a narrow function/method argument check: `CHECK TYPE parameter IS TYPE` inside a function or simple object method lets `claro typecheck` accept correct checked calls and catch mismatched `DO`, `CALL ... WITH`, and `DO object.method ...` arguments -- a narrow object-field assignment check for simple `NEW Class object` plus direct `SET object.field value` cases when the class declares `HAS field TYPE`; validation now covers correct NUMBER, TEXT, and YESNO direct assignments, NUMBER/TEXT/YESNO wrong-type diagnostics, plus NUMBER/TEXT/YESNO-valued unknown-field diagnostics for direct assignments to undeclared fields +- a narrow object-field assignment check for simple `NEW Class object` plus direct `SET object.field value` cases when the class declares `HAS field TYPE`; validation now covers correct NUMBER, TEXT, and YESNO direct assignments, direct `CHECK TYPE` metadata checks for TEXT/YESNO fields, NUMBER/TEXT/YESNO wrong-type diagnostics, plus NUMBER/TEXT/YESNO-valued unknown-field diagnostics for direct assignments to undeclared fields Still needed: - richer typed function signatures and return values diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index c8e57c7..7b1db3b 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -31,7 +31,7 @@ See `CURRENT_STATUS.md` for the detailed feature matrix. 1. Keep beginner-facing docs current and separate from historical release notes. 2. Keep examples aligned with the modern simple syntax (`END`, `DO`, short `SET`, short `ASK`) while documenting older compatibility forms separately. -3. Expand validation around typecheck diagnostics and package/networking safety. Current object-method parameter validation covers one correct `DO object.method ...` call and one wrong-type diagnostic; object-field validation covers correct NUMBER, TEXT, and YESNO direct `SET object.field value` assignments, NUMBER/TEXT/YESNO wrong-type direct assignments, and simple NUMBER/TEXT/YESNO-valued unknown-field diagnostics after `NEW Class object`. +3. Expand validation around typecheck diagnostics and package/networking safety. Current object-method parameter validation covers one correct `DO object.method ...` call and one wrong-type diagnostic; object-field validation covers correct NUMBER, TEXT, and YESNO direct `SET object.field value` assignments, direct `CHECK TYPE` metadata checks for TEXT/YESNO fields, NUMBER/TEXT/YESNO wrong-type direct assignments, and simple NUMBER/TEXT/YESNO-valued unknown-field diagnostics after `NEW Class object`. 4. Add small examples for each foundation feature before adding bigger syntax. ## Complete-platform milestones diff --git a/src/claro.c b/src/claro.c index 3567ba2..250db31 100644 --- a/src/claro.c +++ b/src/claro.c @@ -608,6 +608,6 @@ static void print_help(void){ static int show_examples(void){ const char *items[]={"hello.claro","name_input.claro","quiz.claro","calculator.claro","guessing_game.claro","shopping_list.claro","save_and_load_file.claro","simple_functions.claro","text_and_lists.claro","text_polish.claro","practical_scripting.claro","type_hardening.claro","typed_ask.claro","objects_classes.claro","networking.claro",NULL}; int i; printf("Included beginner examples:\n"); for(i=0;items[i];i++) printf(" examples/%s\n",items[i]); printf("\nRun one with: claro examples/hello.claro\n"); return 0; } static int file_exists_simple(const char *path){ FILE *f=fopen(path,"rb"); if(f){ fclose(f); return 1; } return 0; } static int run_doctor(void){ int ok=1; const char *files[]={"src/claro.c","README.md","assets/Claro_Logo.jpg","lessons/01_hello.claro","examples/hello.claro","tests/01_hello.claro",NULL}; int i; printf("%s\n",CLARO_VERSION); printf("Doctor check:\n"); for(i=0;files[i];i++){ int has=file_exists_simple(files[i]); printf(" %s %s\n",has?"OK":"MISSING",files[i]); if(!has) ok=0; } printf("%s\n",ok?"Claro folder looks ready.":"Some Claro files are missing."); return ok?0:1; } -static int run_validate(void){ int fails=0, i; const char *checks[]={"lessons/01_hello.claro","lessons/02_ask_name.claro","lessons/03_variables.claro","lessons/04_math.claro","lessons/05_if_else.claro","lessons/06_loops.claro","lessons/07_lists.claro","lessons/08_functions.claro","lessons/09_files.claro","lessons/10_final_quiz.claro","examples/hello.claro","examples/name_input.claro","examples/quiz.claro","examples/calculator.claro","examples/guessing_game.claro","examples/shopping_list.claro","examples/save_and_load_file.claro","examples/simple_functions.claro","examples/text_and_lists.claro","examples/text_polish.claro","examples/practical_scripting.claro","examples/type_hardening.claro","examples/objects_classes.claro","examples/networking.claro",NULL}; printf("%s\n",CLARO_VERSION); printf("Stable package validation:\n"); fails+=run_doctor(); fails+=run_tests(); printf("Checking lessons and main examples:\n"); for(i=0;checks[i];i++){ printf(" %s\n",checks[i]); fails+=check_file(checks[i]); } fails+=typecheck_file("tests/typecheck_good.claro"); fails+=typecheck_file("tests/typecheck_container_good.claro"); fails+=typecheck_file("tests/typecheck_function_good.claro"); fails+=typecheck_file("tests/typecheck_function_multi_good.claro"); fails+=typecheck_file("tests/typecheck_method_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_text_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_yesno_good.claro"); fails+=typecheck_file("tests/37_object_field_types.claro"); if(typecheck_file("tests/typecheck_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_container_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_multi_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_method_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_yesno_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_unknown_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_unknown_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_unknown_yesno_bad.claro")==0) fails++; printf("%s\n",fails?"Validation found problems.":"Validation passed. Claro v1.18.26 foundation checks are ready for use."); return fails?1:0; } +static int run_validate(void){ int fails=0, i; const char *checks[]={"lessons/01_hello.claro","lessons/02_ask_name.claro","lessons/03_variables.claro","lessons/04_math.claro","lessons/05_if_else.claro","lessons/06_loops.claro","lessons/07_lists.claro","lessons/08_functions.claro","lessons/09_files.claro","lessons/10_final_quiz.claro","examples/hello.claro","examples/name_input.claro","examples/quiz.claro","examples/calculator.claro","examples/guessing_game.claro","examples/shopping_list.claro","examples/save_and_load_file.claro","examples/simple_functions.claro","examples/text_and_lists.claro","examples/text_polish.claro","examples/practical_scripting.claro","examples/type_hardening.claro","examples/objects_classes.claro","examples/networking.claro",NULL}; printf("%s\n",CLARO_VERSION); printf("Stable package validation:\n"); fails+=run_doctor(); fails+=run_tests(); printf("Checking lessons and main examples:\n"); for(i=0;checks[i];i++){ printf(" %s\n",checks[i]); fails+=check_file(checks[i]); } fails+=typecheck_file("tests/typecheck_good.claro"); fails+=typecheck_file("tests/typecheck_container_good.claro"); fails+=typecheck_file("tests/typecheck_function_good.claro"); fails+=typecheck_file("tests/typecheck_function_multi_good.claro"); fails+=typecheck_file("tests/typecheck_method_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_text_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_yesno_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_check_type_text_yesno_good.claro"); fails+=typecheck_file("tests/37_object_field_types.claro"); if(typecheck_file("tests/typecheck_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_container_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_multi_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_method_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_yesno_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_unknown_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_unknown_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_unknown_yesno_bad.claro")==0) fails++; printf("%s\n",fails?"Validation found problems.":"Validation passed. Claro v1.18.26 foundation checks are ready for use."); return fails?1:0; } int main(int argc,char **argv){ int arg=1, trace=0; if(argc<2){ print_help(); return 0;} if(strcmp(argv[arg],"--trace")==0||strcmp(argv[arg],"trace")==0){ trace=1; arg++; } if(arg>=argc) return 0; if(strcmp(argv[arg],"help")==0||strcmp(argv[arg],"--help")==0){ print_help(); return 0; } if(strcmp(argv[arg],"test")==0) return run_tests(); if(strcmp(argv[arg],"repl")==0) return run_repl(); if(strcmp(argv[arg],"examples")==0) return show_examples(); if(strcmp(argv[arg],"doctor")==0) return run_doctor(); if(strcmp(argv[arg],"validate")==0) return run_validate(); if(strcmp(argv[arg],"package")==0) return run_package_cmd(argc,argv,arg+1); if(strcmp(argv[arg],"ide")==0) return print_ide_info(); if(strcmp(argv[arg],"new")==0&&arg+1=argc){ Runtime rt; int rc; char *mainfile=project_value("main"); if(!mainfile||!*mainfile){ if(mainfile) free(mainfile); mainfile=xstrdup("main.claro"); } rt_init(&rt); rt.trace=trace; rt.script_argc=0; rt.script_argv=NULL; rc=run_file(&rt,mainfile); free(mainfile); return rc; } } { Runtime rt; int rc; rt_init(&rt); rt.trace=trace; rt.script_argc=argc-arg-1; rt.script_argv=argv+arg+1; rc=run_file(&rt,argv[arg]); return rc; } } diff --git a/tests/typecheck_object_field_check_type_text_yesno_good.claro b/tests/typecheck_object_field_check_type_text_yesno_good.claro new file mode 100644 index 0000000..da8ff80 --- /dev/null +++ b/tests/typecheck_object_field_check_type_text_yesno_good.claro @@ -0,0 +1,10 @@ +CLASS Player + HAS name TEXT + HAS ready YESNO +END + +NEW Player player +SET player.name "Ada" +SET player.ready YES +CHECK TYPE player.name IS TEXT +CHECK TYPE player.ready IS YESNO diff --git a/tools/validate_typecheck_diagnostics.py b/tools/validate_typecheck_diagnostics.py index e31aceb..60ed837 100644 --- a/tools/validate_typecheck_diagnostics.py +++ b/tools/validate_typecheck_diagnostics.py @@ -53,6 +53,7 @@ EXPECTED_OK = [ "tests/typecheck_object_field_good.claro", "tests/typecheck_object_field_text_good.claro", "tests/typecheck_object_field_yesno_good.claro", + "tests/typecheck_object_field_check_type_text_yesno_good.claro", "tests/37_object_field_types.claro", ]