From b79db4f25c2b264c8d4a0d6db4eb24d06ce9c438 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Fri, 18 Sep 2026 23:41:22 +0000 Subject: [PATCH] test: cover empty compatibility function returns --- README.md | 2 ++ docs/CURRENT_STATUS.md | 2 +- docs/ROADMAP.md | 1 + src/claro.c | 2 +- tests/test_validate_typecheck_diagnostics.py | 6 ++++++ tests/typecheck_function_compat_empty_return_bad.claro | 4 ++++ tools/validate_typecheck_diagnostics.py | 3 +++ 7 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 tests/typecheck_function_compat_empty_return_bad.claro diff --git a/README.md b/README.md index 71b7f14..1ed5999 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,8 @@ The same repair applies to object methods and older compatibility methods, and n Method Player.score needs a return type after RETURNS. Add a type such as NUMBER. ``` +An empty typed `RETURN` is also rejected in both modern and compatibility functions and methods. Add an expression of the declared type, such as `RETURN amount` for a `NUMBER` return. + `CHECK TYPE` names a real Claro type. If a type name is misspelled, the checker explains the allowed beginner types instead of reporting a confusing value mismatch: ```text diff --git a/docs/CURRENT_STATUS.md b/docs/CURRENT_STATUS.md index 6f55b51..2f0a3b8 100644 --- a/docs/CURRENT_STATUS.md +++ b/docs/CURRENT_STATUS.md @@ -62,7 +62,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 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`, 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. - 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 - top-level function declarations now reject repeated names with a direct repair hint, so two `TEACH greet` blocks cannot silently compete for one callable function; a missing function name after `TEACH` gets a direct beginner-facing repair hint, and a missing method name inside `CLASS` names the class and gives a method example diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 2d1da8a..37d2d3b 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -85,6 +85,7 @@ Keep declared return types honest: `claro typecheck` now reports friendly diagno 8q.9. Keep missing return-type diagnostics aligned across functions and methods: modern and compatibility methods now name the complete `Class.method` identity when `RETURNS` has no type, with focused fixtures in the typecheck and release validation matrices. 8q.10. Keep return statements beginner-readable: typed returns now identify simple extra tokens after a value and explain that `RETURN` accepts one expression, with focused release validation coverage. 8q.11. Keep extra-token return diagnostics aligned across syntax generations: modern and compatibility functions and object methods now have focused fixtures for `RETURN value extra`, so errors keep the function or class-and-method name and the same repair hint. +8q.12. Keep empty typed-return diagnostics aligned across syntax generations: modern and compatibility functions and object methods now have focused fixtures for bare `RETURN`, so each form explains that the declared type needs an expression. ### 1. Strong static types diff --git a/src/claro.c b/src/claro.c index 81648d5..8bb7b79 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_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_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 4d4e87d..69643a1 100644 --- a/tests/test_validate_typecheck_diagnostics.py +++ b/tests/test_validate_typecheck_diagnostics.py @@ -120,6 +120,12 @@ class ValidateTypecheckDiagnosticsTests(unittest.TestCase): MODULE.EXPECTED, ) + def test_includes_compatibility_function_empty_return_fixture(self): + self.assertIn( + "tests/typecheck_function_compat_empty_return_bad.claro", + MODULE.EXPECTED, + ) + def test_includes_empty_compatibility_method_return_fixture(self): self.assertIn( "tests/typecheck_method_compat_empty_return_bad.claro", diff --git a/tests/typecheck_function_compat_empty_return_bad.claro b/tests/typecheck_function_compat_empty_return_bad.claro new file mode 100644 index 0000000..eea43b4 --- /dev/null +++ b/tests/typecheck_function_compat_empty_return_bad.claro @@ -0,0 +1,4 @@ +TEACH square TAKES amount RETURNS NUMBER + CHECK TYPE amount IS NUMBER + RETURN +LEARNED diff --git a/tools/validate_typecheck_diagnostics.py b/tools/validate_typecheck_diagnostics.py index b8448e5..87468b3 100644 --- a/tools/validate_typecheck_diagnostics.py +++ b/tools/validate_typecheck_diagnostics.py @@ -73,6 +73,9 @@ EXPECTED = { "tests/typecheck_function_compat_return_extra_tokens_bad.claro": [ "tests/typecheck_function_compat_return_extra_tokens_bad.claro:2: Function square has extra text after return value amount. Keep only one expression after RETURN.", ], + "tests/typecheck_function_compat_empty_return_bad.claro": [ + "tests/typecheck_function_compat_empty_return_bad.claro:3: Function square needs a NUMBER value after RETURN. Add a NUMBER expression.", + ], "tests/typecheck_method_return_extra_tokens_bad.claro": [ "tests/typecheck_method_return_extra_tokens_bad.claro:4: Method Player.total has extra text after return value 1. Keep only one expression after RETURN.", ],