From 1bc11207ef0f0925af5abcc2ce6b2f1c263573d4 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Sat, 19 Sep 2026 12:01:25 +0000 Subject: [PATCH] test: cover compatibility function missing returns --- docs/CURRENT_STATUS.md | 2 +- docs/ROADMAP.md | 2 +- src/claro.c | 2 +- tests/test_validate_typecheck_diagnostics.py | 13 +++++++++++++ ...pecheck_function_compat_missing_return_bad.claro | 3 +++ tools/validate_typecheck_diagnostics.py | 3 +++ 6 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/typecheck_function_compat_missing_return_bad.claro diff --git a/docs/CURRENT_STATUS.md b/docs/CURRENT_STATUS.md index 00dcdcd..558859a 100644 --- a/docs/CURRENT_STATUS.md +++ b/docs/CURRENT_STATUS.md @@ -63,7 +63,7 @@ Ready now: - `TYPE OF` rejects extra words after its result name with a direct repair hint, so `TYPE OF score AS kind extra` explains that only one result name belongs there; typed `TEACH ... RETURNS TYPE` declarations likewise reject extra words after the return type with a direct repair hint - typed `TEACH ... RETURNS` declarations reject a missing return type with a direct repair hint, such as `Function greet needs a return type after RETURNS. Add a type such as NUMBER.` The same diagnostic names the complete class and method, including compatibility `TAKES` / `LEARNED` methods: `Method Player.score needs a return type after RETURNS. Add a type such as NUMBER.` - typed list/map checks through `claro typecheck`, including a nested `LIST OF MAP` insertion example -- simple function and object-method return checks with `TEACH name ... RETURNS TYPE`, including learner-facing diagnostics for unknown declared return types, mismatched or not-yet-inferable `RETURN` expressions (including method-specific diagnostics naming the class and method, with modern and compatibility method coverage), empty `RETURN` statements in modern and compatibility functions and methods, declarations that contain no `RETURN`, and declarations whose only return is inside an incomplete conditional; missing return types are checked for modern functions and both modern and compatibility methods, with compatibility-function coverage as well; extra text after a return value is rejected consistently in modern functions, compatibility `TAKES` / `LEARNED` functions, and both method forms; `RETURNS` is case-insensitive like other Claro keywords and has positive coverage in both modern and compatibility function forms, including lowercase compatibility declarations and lowercase compatibility method declarations, plus a lowercase compatibility-method mismatch diagnostic; positive function-return coverage includes numeric multiplication; compatibility methods now have dedicated positive numeric addition, subtraction, division, and multiplication return fixtures plus compatibility addition, subtraction, division, and multiplication diagnostic fixtures; NUMBER return diagnostics name a known TEXT operand and arithmetic operation instead of hiding the cause behind a generic mismatch, with focused addition, subtraction, multiplication, and division coverage for functions and methods; typed-function return diagnostics now have focused subtraction and division positives alongside multiplication coverage. Text concatenation into a TEXT field has focused positive fixtures for both operand orders, including concatenation of two TEXT object fields. Each numeric operator names the text operand and explains that it needs NUMBER values. +- simple function and object-method return checks with `TEACH name ... RETURNS TYPE`, including learner-facing diagnostics for unknown declared return types, mismatched or not-yet-inferable `RETURN` expressions (including method-specific diagnostics naming the class and method, with modern and compatibility method coverage), empty `RETURN` statements in modern and compatibility functions and methods, declarations that contain no `RETURN` in modern and compatibility function forms, and declarations whose only return is inside an incomplete conditional; missing return types are checked for modern functions and both modern and compatibility methods, with a compatibility-function fixture as well; extra text after a return value is rejected consistently in modern functions, compatibility `TAKES` / `LEARNED` functions, and both method forms; `RETURNS` is case-insensitive like other Claro keywords and has positive coverage in both modern and compatibility function forms, including lowercase compatibility declarations and lowercase compatibility method declarations, plus a lowercase compatibility-method mismatch diagnostic; positive function-return coverage includes numeric multiplication; compatibility methods now have dedicated positive numeric addition, subtraction, division, and multiplication return fixtures plus compatibility addition, subtraction, division, and multiplication diagnostic fixtures; NUMBER return diagnostics name a known TEXT operand and arithmetic operation instead of hiding the cause behind a generic mismatch, with focused addition, subtraction, multiplication, and division coverage for functions and methods; typed-function return diagnostics now have focused subtraction and division positives alongside multiplication coverage. Text concatenation into a TEXT field has focused positive fixtures for both operand orders, including concatenation of two TEXT object fields. Each numeric operator names the text operand and explains that it needs NUMBER values. - compatibility `TAKES` / `LEARNED` functions also have focused positive numeric-addition, subtraction, division, and multiplication return fixtures, keeping arithmetic return coverage aligned with modern functions and compatibility methods. - 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, catch mismatched `DO`, `CALL ... WITH`, `DO object.method ...`, and compatibility `CALL object.method WITH ...` arguments, including checked methods that appear after another method in the same class, report missing checked function and method arguments, report missing unchecked arguments for simple functions and simple object methods in both modern `DO` and compatibility `CALL ... WITH` forms, treat empty compatibility calls such as `CALL greet WITH` and `CALL player.rename WITH` as missing-argument mistakes, catch extra arguments to simple functions and checked methods even when the checked method appears after another method in the same class, catch modern `DO` and compatibility `CALL ... WITH` calls to undeclared simple functions, explain when `DO object.method ...` or compatibility `CALL object.method ...` happens before the object is created with `NEW` even if the method name is also wrong, and catch modern plus compatibility calls to undeclared object methods with a class-specific `TEACH` hint - function and method declarations now reject repeated parameter names with a direct repair hint before calls are checked, including modern and compatibility `TAKES` / `LEARNED` functions and methods; object methods with the same name are also rejected within a class with a rename hint in both modern and compatibility method syntax diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 64fe6d5..07c8ca8 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -41,7 +41,7 @@ See `CURRENT_STATUS.md` for the detailed feature matrix. - Keep method field examples balanced across syntax generations: modern and compatibility `TAKES` / `LEARNED` NUMBER, TEXT, and YESNO assignments now have positive fixtures beside the modern and compatibility mismatch fixtures, and modern plus compatibility YESNO method-field metadata now have dedicated positive fixtures beside the negative fixture. - Keep IDE metadata aligned with the current beginner syntax: typed-language keywords such as `RETURNS`, `CHECK`, and `TYPE` are now included in the metadata used by editor helpers. - Keep compatibility-call coverage aligned with modern calls: empty `CALL object.method WITH` forms now have a focused missing-argument diagnostic fixture alongside the modern `DO object.method` case. -Keep declared return types honest: `claro typecheck` now reports friendly diagnostics for unknown declared return types, missing return types, mismatched, not-yet-inferable, and empty return expressions (including compatibility `TAKES` / `LEARNED` methods), declarations with no `RETURN`, and incomplete conditional branches, when a simple function or object method declares `RETURNS TYPE`; missing-type coverage includes modern functions and both modern and compatibility methods, with a compatibility-function fixture as well. The declaration keyword is case-insensitive like other Claro keywords, with positive coverage in modern and compatibility function forms, including lowercase compatibility declarations and lowercase compatibility method declarations, plus a lowercase compatibility-method mismatch fixture. Complete `IF`/`ELSE` return branches, including nested complete conditionals in functions and methods, are accepted, and modern and compatibility function syntax plus compatibility method syntax are covered by focused fixtures. `CHECK TYPE` parameter metadata also informs arithmetic return-expression checking, including object methods; positive numeric multiplication return coverage now sits beside the mismatch fixtures, including a dedicated compatibility-method multiplication success fixture; typed methods can also return class-declared fields by simple name, with positive and mismatch fixtures in both modern and compatibility method syntax, and unknown method return expressions now have dedicated modern and compatibility diagnostic fixtures, and NUMBER return expressions with known TEXT arithmetic operands identify the operation and offending operand, including focused addition, subtraction, multiplication, and division coverage for functions and methods. Compatibility method subtraction diagnostics are also covered alongside the existing addition diagnostic. Full path-sensitive analysis across nested conditionals and loops remains planned. +Keep declared return types honest: `claro typecheck` now reports friendly diagnostics for unknown declared return types, missing return types, mismatched, not-yet-inferable, and empty return expressions (including compatibility `TAKES` / `LEARNED` methods), declarations with no `RETURN` in modern and compatibility function forms, and incomplete conditional branches, when a simple function or object method declares `RETURNS TYPE`; missing-type coverage includes modern functions and both modern and compatibility methods, with a compatibility-function fixture as well. The declaration keyword is case-insensitive like other Claro keywords, with positive coverage in modern and compatibility function forms, including lowercase compatibility declarations and lowercase compatibility method declarations, plus a lowercase compatibility-method mismatch fixture. Complete `IF`/`ELSE` return branches, including nested complete conditionals in functions and methods, are accepted, and modern and compatibility function syntax plus compatibility method syntax are covered by focused fixtures. `CHECK TYPE` parameter metadata also informs arithmetic return-expression checking, including object methods; positive numeric multiplication return coverage now sits beside the mismatch fixtures, including a dedicated compatibility-method multiplication success fixture; typed methods can also return class-declared fields by simple name, with positive and mismatch fixtures in both modern and compatibility method syntax, and unknown method return expressions now have dedicated modern and compatibility diagnostic fixtures, and NUMBER return expressions with known TEXT arithmetic operands identify the operation and offending operand, including focused addition, subtraction, multiplication, and division coverage for functions and methods. Compatibility method subtraction diagnostics are also covered alongside the existing addition diagnostic. Full path-sensitive analysis across nested conditionals and loops remains planned. 7. Keep method-body field diagnostics learner-facing: typed methods now name the class method when a simple class field receives a known mismatch in `CHECK TYPE` or assignment, or a known TEXT operand in a NUMBER expression, with matching text and numeric coverage in modern and compatibility method syntax; direct assignments to undeclared method fields now report the missing field when the value type is known, and bare `CHECK TYPE missing IS TYPE` statements inside methods now use the expected type in the repair hint in both modern and compatibility method syntax; broader control-flow and object-flow analysis remains planned. 8: Keep method-body coverage balanced across beginner field types and syntax generations: YESNO field assignment mismatches are now validated for both modern `DO` and compatibility `CALL ... WITH` method syntax, method-body `CHECK TYPE` metadata mismatches now have matching compatibility `TAKES` / `LEARNED` coverage alongside the modern form, compatibility YESNO field metadata has dedicated positive and negative fixtures, and compatibility method assignments to undeclared fields have the same focused missing-field diagnostic as modern methods, including a beginner-facing fallback when the assigned expression is not inferable yet. diff --git a/src/claro.c b/src/claro.c index 8bb7b79..799927c 100644 --- a/src/claro.c +++ b/src/claro.c @@ -782,6 +782,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]); } { const char *typecheck_good[] = {"tests/typecheck_function_branch_complete_good.claro","tests/typecheck_function_nested_branch_complete_good.claro","tests/typecheck_function_return_expression_good.claro","tests/typecheck_function_return_multiplication_good.claro","tests/typecheck_method_call_good.claro","tests/typecheck_method_field_assignment_good.claro","tests/typecheck_method_text_concat_good.claro","tests/typecheck_method_compat_text_concat_good.claro","tests/typecheck_method_text_field_assignment_good.claro","tests/typecheck_method_compat_text_field_assignment_good.claro","tests/typecheck_method_compat_yesno_field_assignment_good.claro","tests/typecheck_method_field_check_type_good.claro","tests/typecheck_method_compat_field_check_type_good.claro","tests/typecheck_method_compat_return_good.claro","tests/typecheck_method_compat_lowercase_return_good.claro","tests/typecheck_method_compat_return_multiplication_good.claro","tests/typecheck_method_compat_return_addition_good.claro","tests/typecheck_method_nested_branch_complete_good.claro","tests/typecheck_method_return_expression_good.claro","tests/typecheck_method_return_addition_good.claro","tests/typecheck_method_return_good.claro","tests/typecheck_nested_container_good.claro","tests/typecheck_object_alias_method_call_good.claro","tests/typecheck_object_alias_method_do_good.claro","tests/typecheck_object_field_alias_good.claro","tests/typecheck_object_field_check_type_chained_alias_text_good.claro","tests/typecheck_object_field_check_type_yesno_good.claro","tests/typecheck_object_field_division_good.claro","tests/typecheck_object_field_multiplication_good.claro","tests/typecheck_object_field_text_concat_good.claro","tests/typecheck_object_field_text_concat_reverse_good.claro","tests/typecheck_object_field_subtraction_good.claro",NULL}; const char *typecheck_bad[] = {"tests/typecheck_function_branch_missing_return_bad.claro","tests/typecheck_function_call_missing_unchecked_arg_bad.claro","tests/typecheck_function_call_unknown_bad.claro","tests/typecheck_function_extra_arg_bad.claro","tests/typecheck_function_missing_arg_bad.claro","tests/typecheck_function_missing_return_bad.claro","tests/typecheck_function_return_expression_bad.claro","tests/typecheck_function_return_arithmetic_bad.claro","tests/typecheck_invalid_expected_type_bad.claro","tests/typecheck_missing_expression_bad.claro","tests/typecheck_missing_expression_with_is_bad.claro","tests/typecheck_invalid_return_type_bad.claro","tests/typecheck_method_call_bad.claro","tests/typecheck_method_call_unknown_method_bad.claro","tests/typecheck_method_call_unknown_object_bad.claro","tests/typecheck_method_call_unknown_object_unknown_method_bad.claro","tests/typecheck_method_compat_return_bad.claro","tests/typecheck_method_compat_return_multiplication_bad.claro","tests/typecheck_method_duplicate_name_bad.claro","tests/typecheck_duplicate_field_bad.claro","tests/typecheck_duplicate_class_bad.claro","tests/typecheck_method_extra_arg_bad.claro","tests/typecheck_method_invalid_return_type_bad.claro","tests/typecheck_method_missing_arg_bad.claro","tests/typecheck_method_missing_return_bad.claro","tests/typecheck_method_missing_unchecked_arg_bad.claro","tests/typecheck_method_return_bad.claro","tests/typecheck_method_return_addition_bad.claro","tests/typecheck_method_return_expression_bad.claro","tests/typecheck_method_second_method_bad.claro","tests/typecheck_method_second_method_extra_arg_bad.claro","tests/typecheck_method_unknown_method_bad.claro","tests/typecheck_method_field_assignment_bad.claro","tests/typecheck_method_compat_unknown_field_bad.claro","tests/typecheck_method_unknown_field_typed_bad.claro","tests/typecheck_method_compat_unknown_field_typed_bad.claro","tests/typecheck_method_unknown_field_expression_bad.claro","tests/typecheck_method_text_field_assignment_bad.claro","tests/typecheck_method_compat_text_field_assignment_bad.claro","tests/typecheck_method_yesno_field_assignment_bad.claro","tests/typecheck_method_compat_yesno_field_assignment_bad.claro","tests/typecheck_method_field_check_type_bad.claro","tests/typecheck_method_compat_field_check_type_bad.claro","tests/typecheck_method_unknown_object_bad.claro","tests/typecheck_object_alias_method_bad.claro","tests/typecheck_object_alias_method_call_bad.claro","tests/typecheck_object_field_addition_bad.claro","tests/typecheck_object_field_after_method_bad.claro","tests/typecheck_object_field_alias_bad.claro","tests/typecheck_object_field_chained_alias_bad.claro","tests/typecheck_object_field_division_bad.claro","tests/typecheck_object_field_multiplication_bad.claro","tests/typecheck_object_field_subtraction_bad.claro","tests/typecheck_object_field_typed_bad.claro","tests/typecheck_object_field_unknown_object_bad.claro","tests/typecheck_object_field_unknown_typed_bad.claro","tests/typecheck_missing_field_type_bad.claro","tests/typecheck_extra_class_tokens_bad.claro","tests/typecheck_extra_new_tokens_bad.claro","tests/typecheck_extra_field_tokens_bad.claro",NULL}; for(i=0;typecheck_good[i];i++) fails+=typecheck_file(typecheck_good[i]); for(i=0;typecheck_bad[i];i++) if(typecheck_file(typecheck_bad[i])==0) fails++; } 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_return_good.claro"); fails+=typecheck_file("tests/typecheck_function_compat_return_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_expression_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_compound_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_subtraction_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_text_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_text_concat_fields_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/typecheck_object_field_check_type_chained_alias_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_duplicate_param_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_return_extra_tokens_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_compat_return_extra_tokens_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_compat_empty_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_compat_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_empty_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_multi_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_missing_unchecked_arg_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_unknown_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_method_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_method_branch_missing_return_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_unknown_expression_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_expression_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_compound_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_text_expression_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++; if(typecheck_file("tests/typecheck_object_field_check_type_unknown_object_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_alias_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_chained_alias_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]); } { const char *typecheck_good[] = {"tests/typecheck_function_branch_complete_good.claro","tests/typecheck_function_nested_branch_complete_good.claro","tests/typecheck_function_return_expression_good.claro","tests/typecheck_function_return_multiplication_good.claro","tests/typecheck_method_call_good.claro","tests/typecheck_method_field_assignment_good.claro","tests/typecheck_method_text_concat_good.claro","tests/typecheck_method_compat_text_concat_good.claro","tests/typecheck_method_text_field_assignment_good.claro","tests/typecheck_method_compat_text_field_assignment_good.claro","tests/typecheck_method_compat_yesno_field_assignment_good.claro","tests/typecheck_method_field_check_type_good.claro","tests/typecheck_method_compat_field_check_type_good.claro","tests/typecheck_method_compat_return_good.claro","tests/typecheck_method_compat_lowercase_return_good.claro","tests/typecheck_method_compat_return_multiplication_good.claro","tests/typecheck_method_compat_return_addition_good.claro","tests/typecheck_method_nested_branch_complete_good.claro","tests/typecheck_method_return_expression_good.claro","tests/typecheck_method_return_addition_good.claro","tests/typecheck_method_return_good.claro","tests/typecheck_nested_container_good.claro","tests/typecheck_object_alias_method_call_good.claro","tests/typecheck_object_alias_method_do_good.claro","tests/typecheck_object_field_alias_good.claro","tests/typecheck_object_field_check_type_chained_alias_text_good.claro","tests/typecheck_object_field_check_type_yesno_good.claro","tests/typecheck_object_field_division_good.claro","tests/typecheck_object_field_multiplication_good.claro","tests/typecheck_object_field_text_concat_good.claro","tests/typecheck_object_field_text_concat_reverse_good.claro","tests/typecheck_object_field_subtraction_good.claro",NULL}; const char *typecheck_bad[] = {"tests/typecheck_function_branch_missing_return_bad.claro","tests/typecheck_function_call_missing_unchecked_arg_bad.claro","tests/typecheck_function_call_unknown_bad.claro","tests/typecheck_function_extra_arg_bad.claro","tests/typecheck_function_missing_arg_bad.claro","tests/typecheck_function_missing_return_bad.claro","tests/typecheck_function_compat_missing_return_bad.claro","tests/typecheck_function_return_expression_bad.claro","tests/typecheck_function_return_arithmetic_bad.claro","tests/typecheck_invalid_expected_type_bad.claro","tests/typecheck_missing_expression_bad.claro","tests/typecheck_missing_expression_with_is_bad.claro","tests/typecheck_invalid_return_type_bad.claro","tests/typecheck_method_call_bad.claro","tests/typecheck_method_call_unknown_method_bad.claro","tests/typecheck_method_call_unknown_object_bad.claro","tests/typecheck_method_call_unknown_object_unknown_method_bad.claro","tests/typecheck_method_compat_return_bad.claro","tests/typecheck_method_compat_return_multiplication_bad.claro","tests/typecheck_method_duplicate_name_bad.claro","tests/typecheck_duplicate_field_bad.claro","tests/typecheck_duplicate_class_bad.claro","tests/typecheck_method_extra_arg_bad.claro","tests/typecheck_method_invalid_return_type_bad.claro","tests/typecheck_method_missing_arg_bad.claro","tests/typecheck_method_missing_return_bad.claro","tests/typecheck_method_missing_unchecked_arg_bad.claro","tests/typecheck_method_return_bad.claro","tests/typecheck_method_return_addition_bad.claro","tests/typecheck_method_return_expression_bad.claro","tests/typecheck_method_second_method_bad.claro","tests/typecheck_method_second_method_extra_arg_bad.claro","tests/typecheck_method_unknown_method_bad.claro","tests/typecheck_method_field_assignment_bad.claro","tests/typecheck_method_compat_unknown_field_bad.claro","tests/typecheck_method_unknown_field_typed_bad.claro","tests/typecheck_method_compat_unknown_field_typed_bad.claro","tests/typecheck_method_unknown_field_expression_bad.claro","tests/typecheck_method_text_field_assignment_bad.claro","tests/typecheck_method_compat_text_field_assignment_bad.claro","tests/typecheck_method_yesno_field_assignment_bad.claro","tests/typecheck_method_compat_yesno_field_assignment_bad.claro","tests/typecheck_method_field_check_type_bad.claro","tests/typecheck_method_compat_field_check_type_bad.claro","tests/typecheck_method_unknown_object_bad.claro","tests/typecheck_object_alias_method_bad.claro","tests/typecheck_object_alias_method_call_bad.claro","tests/typecheck_object_field_addition_bad.claro","tests/typecheck_object_field_after_method_bad.claro","tests/typecheck_object_field_alias_bad.claro","tests/typecheck_object_field_chained_alias_bad.claro","tests/typecheck_object_field_division_bad.claro","tests/typecheck_object_field_multiplication_bad.claro","tests/typecheck_object_field_subtraction_bad.claro","tests/typecheck_object_field_typed_bad.claro","tests/typecheck_object_field_unknown_object_bad.claro","tests/typecheck_object_field_unknown_typed_bad.claro","tests/typecheck_missing_field_type_bad.claro","tests/typecheck_extra_class_tokens_bad.claro","tests/typecheck_extra_new_tokens_bad.claro","tests/typecheck_extra_field_tokens_bad.claro",NULL}; for(i=0;typecheck_good[i];i++) fails+=typecheck_file(typecheck_good[i]); for(i=0;typecheck_bad[i];i++) if(typecheck_file(typecheck_bad[i])==0) fails++; } 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_return_good.claro"); fails+=typecheck_file("tests/typecheck_function_compat_return_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_expression_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_compound_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_subtraction_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_text_good.claro"); fails+=typecheck_file("tests/typecheck_object_field_text_concat_fields_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/typecheck_object_field_check_type_chained_alias_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_duplicate_param_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_return_extra_tokens_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_compat_return_extra_tokens_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_compat_empty_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_compat_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_empty_return_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_multi_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_missing_unchecked_arg_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_function_unknown_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_method_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_method_branch_missing_return_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_unknown_expression_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_expression_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_compound_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_text_expression_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++; if(typecheck_file("tests/typecheck_object_field_check_type_unknown_object_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_alias_bad.claro")==0) fails++; if(typecheck_file("tests/typecheck_object_field_check_type_chained_alias_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/test_validate_typecheck_diagnostics.py b/tests/test_validate_typecheck_diagnostics.py index af951c7..a4b3c61 100644 --- a/tests/test_validate_typecheck_diagnostics.py +++ b/tests/test_validate_typecheck_diagnostics.py @@ -226,6 +226,12 @@ class ValidateTypecheckDiagnosticsTests(unittest.TestCase): MODULE.EXPECTED_OK, ) + def test_includes_compatibility_function_missing_return_fixture(self): + self.assertIn( + "tests/typecheck_function_compat_missing_return_bad.claro", + MODULE.EXPECTED, + ) + def test_includes_lowercase_compatibility_method_return_success_fixture(self): self.assertIn( "tests/typecheck_method_compat_lowercase_return_good.claro", @@ -360,6 +366,13 @@ class ValidateTypecheckDiagnosticsTests(unittest.TestCase): ): self.assertIn(f'"{fixture}"', source) + def test_release_validation_runs_compatibility_function_missing_return_fixture(self): + source = (ROOT / "src" / "claro.c").read_text() + self.assertIn( + '"tests/typecheck_function_compat_missing_return_bad.claro"', + source, + ) + def test_release_validation_runs_method_call_fixture(self): result = subprocess.run( [str(ROOT / "claro"), "validate"], diff --git a/tests/typecheck_function_compat_missing_return_bad.claro b/tests/typecheck_function_compat_missing_return_bad.claro new file mode 100644 index 0000000..83881c8 --- /dev/null +++ b/tests/typecheck_function_compat_missing_return_bad.claro @@ -0,0 +1,3 @@ +TEACH square TAKES amount RETURNS NUMBER + CHECK TYPE amount IS NUMBER +LEARNED diff --git a/tools/validate_typecheck_diagnostics.py b/tools/validate_typecheck_diagnostics.py index 6ecb23c..c4bb5c7 100644 --- a/tools/validate_typecheck_diagnostics.py +++ b/tools/validate_typecheck_diagnostics.py @@ -136,6 +136,9 @@ EXPECTED = { "tests/typecheck_function_missing_return_bad.claro": [ "tests/typecheck_function_missing_return_bad.claro:3: Function square declares RETURNS NUMBER but has no RETURN statement. Add RETURN with a NUMBER value.", ], + "tests/typecheck_function_compat_missing_return_bad.claro": [ + "tests/typecheck_function_compat_missing_return_bad.claro:3: Function square declares RETURNS NUMBER but has no RETURN statement. Add RETURN with a NUMBER value.", + ], "tests/typecheck_function_branch_missing_return_bad.claro": [ "tests/typecheck_function_branch_missing_return_bad.claro:5: Function choose declares RETURNS NUMBER but does not return a NUMBER value on every path. Add RETURN to each branch or after the conditional.", ],