test: add object field CHECK TYPE TEXT positive fixture

This commit is contained in:
Hermes Agent
2026-07-13 09:03:02 +00:00
parent 765271aab6
commit b2c2975696
6 changed files with 16 additions and 3 deletions
+5
View File
@@ -1,5 +1,10 @@
# Changelog # Changelog
## v1.18.26-dev object field CHECK TYPE TEXT positive validation
- Added a dedicated positive `claro typecheck` fixture for direct object-field metadata checks: `CHECK TYPE player.name IS TEXT` is accepted after `NEW Player player` and `SET player.name "Ada"` when the class declares `HAS name TEXT`.
- Wired the fixture into both the typecheck diagnostics validator and `claro validate`; no production typechecker behavior change was needed because the existing direct object-field metadata path already accepts the TEXT check.
## v1.18.26-dev object field CHECK TYPE NUMBER positive validation ## v1.18.26-dev object field CHECK TYPE NUMBER positive validation
- Added a focused positive `claro typecheck` fixture for direct object-field metadata checks: `CHECK TYPE player.score IS NUMBER` is accepted after `NEW Player player` and `SET player.score 10` when the class declares `HAS score NUMBER`. - Added a focused positive `claro typecheck` fixture for direct object-field metadata checks: `CHECK TYPE player.score IS NUMBER` is accepted after `NEW Player player` and `SET player.score 10` when the class declares `HAS score NUMBER`.
+1 -1
View File
@@ -210,7 +210,7 @@ Output:
Object Player has no field enabled. Check the field name or add HAS enabled YESNO to the class. Object Player has no field enabled. Check the field name or add HAS enabled 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_check_type_number_good.claro` checks that direct `CHECK TYPE player.score IS NUMBER` metadata is accepted, `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_check_type_number_bad.claro` checks that `CHECK TYPE player.score IS TEXT` reports the NUMBER metadata mismatch, `tests/typecheck_object_field_check_type_text_bad.claro` checks that `CHECK TYPE player.name IS NUMBER` reports the TEXT metadata mismatch, `tests/typecheck_object_field_check_type_yesno_bad.claro` checks that `CHECK TYPE player.ready IS TEXT` reports the YESNO metadata mismatch, `tests/typecheck_object_field_check_type_unknown_number_bad.claro` checks that `CHECK TYPE player.level IS NUMBER` reports the unknown-field metadata diagnostic, `tests/typecheck_object_field_check_type_unknown_text_bad.claro` checks that `CHECK TYPE player.nickname IS TEXT` reports the TEXT unknown-field metadata diagnostic, `tests/typecheck_object_field_check_type_unknown_yesno_bad.claro` checks that `CHECK TYPE player.enabled IS YESNO` reports the YESNO unknown-field metadata diagnostic, `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_number_good.claro` checks that direct `CHECK TYPE player.score IS NUMBER` metadata is accepted, `tests/typecheck_object_field_check_type_text_good.claro` checks the dedicated direct `CHECK TYPE player.name IS TEXT` metadata path, `tests/typecheck_object_field_check_type_text_yesno_good.claro` keeps combined TEXT/YESNO metadata checks covered, `tests/typecheck_object_field_check_type_number_bad.claro` checks that `CHECK TYPE player.score IS TEXT` reports the NUMBER metadata mismatch, `tests/typecheck_object_field_check_type_text_bad.claro` checks that `CHECK TYPE player.name IS NUMBER` reports the TEXT metadata mismatch, `tests/typecheck_object_field_check_type_yesno_bad.claro` checks that `CHECK TYPE player.ready IS TEXT` reports the YESNO metadata mismatch, `tests/typecheck_object_field_check_type_unknown_number_bad.claro` checks that `CHECK TYPE player.level IS NUMBER` reports the unknown-field metadata diagnostic, `tests/typecheck_object_field_check_type_unknown_text_bad.claro` checks that `CHECK TYPE player.nickname IS TEXT` reports the TEXT unknown-field metadata diagnostic, `tests/typecheck_object_field_check_type_unknown_yesno_bad.claro` checks that `CHECK TYPE player.enabled IS YESNO` reports the YESNO unknown-field metadata diagnostic, `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 hint, `tests/typecheck_object_field_unknown_text_bad.claro` checks a TEXT-valued unknown-field hint, `tests/typecheck_object_field_unknown_yesno_bad.claro` checks a YESNO-valued unknown-field hint, and `tests/37_object_field_types.claro` keeps the runtime object-field example passing.
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. 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.
+1 -1
View File
@@ -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. 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. 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, direct `CHECK TYPE` metadata checks for TEXT/YESNO fields plus negative NUMBER/TEXT/YESNO metadata mismatches, NUMBER/TEXT/YESNO-expectation unknown-field `CHECK TYPE` diagnostics, 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 acceptance for NUMBER/TEXT/YESNO fields, negative NUMBER/TEXT/YESNO metadata mismatches, NUMBER/TEXT/YESNO-expectation unknown-field `CHECK TYPE` diagnostics, 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. 4. Add small examples for each foundation feature before adding bigger syntax.
## Complete-platform milestones ## Complete-platform milestones
+1 -1
View File
@@ -631,6 +631,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 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 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_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/typecheck_object_field_check_type_number_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++; if(typecheck_file("tests/typecheck_object_field_check_type_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_yesno_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_number_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_unknown_number_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_unknown_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_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_number_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_check_type_text_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++; if(typecheck_file("tests/typecheck_object_field_check_type_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_yesno_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_number_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_unknown_number_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_unknown_text_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_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) return create_new_project(argv[arg+1]); if(strcmp(argv[arg],"fmt")==0&&arg+1<argc) return fmt_file(argv[arg+1]); if(strcmp(argv[arg],"check")==0&&arg+1<argc) return check_file(argv[arg+1]); if(strcmp(argv[arg],"typecheck")==0&&arg+1<argc) return typecheck_file(argv[arg+1]); if(strcmp(argv[arg],"version")==0||strcmp(argv[arg],"--version")==0){ puts(CLARO_VERSION); return 0; } if(strcmp(argv[arg],"run")==0){ arg++; if(arg>=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; } } 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) return create_new_project(argv[arg+1]); if(strcmp(argv[arg],"fmt")==0&&arg+1<argc) return fmt_file(argv[arg+1]); if(strcmp(argv[arg],"check")==0&&arg+1<argc) return check_file(argv[arg+1]); if(strcmp(argv[arg],"typecheck")==0&&arg+1<argc) return typecheck_file(argv[arg+1]); if(strcmp(argv[arg],"version")==0||strcmp(argv[arg],"--version")==0){ puts(CLARO_VERSION); return 0; } if(strcmp(argv[arg],"run")==0){ arg++; if(arg>=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; } }
@@ -0,0 +1,7 @@
CLASS Player
HAS name TEXT
END
NEW Player player
SET player.name "Ada"
CHECK TYPE player.name IS TEXT
+1
View File
@@ -72,6 +72,7 @@ EXPECTED_OK = [
"tests/typecheck_object_field_text_good.claro", "tests/typecheck_object_field_text_good.claro",
"tests/typecheck_object_field_yesno_good.claro", "tests/typecheck_object_field_yesno_good.claro",
"tests/typecheck_object_field_check_type_number_good.claro", "tests/typecheck_object_field_check_type_number_good.claro",
"tests/typecheck_object_field_check_type_text_good.claro",
"tests/typecheck_object_field_check_type_text_yesno_good.claro", "tests/typecheck_object_field_check_type_text_yesno_good.claro",
"tests/37_object_field_types.claro", "tests/37_object_field_types.claro",
] ]