From bd96963fb89f59b3858b22e3e29d6d20ac6f8b2e Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Tue, 9 Jun 2026 03:10:29 -0600 Subject: [PATCH] feat: add multi-parameter function type diagnostics --- CHANGELOG.md | 6 ++++++ README.md | 11 +++++++++++ docs/ADVANCED_STATIC_TYPING.md | 22 +++++++++++++++++++++- docs/CURRENT_STATUS.md | 2 +- src/claro.c | 4 ++-- tests/typecheck_function_multi_bad.claro | 8 ++++++++ tests/typecheck_function_multi_good.claro | 8 ++++++++ tools/validate_typecheck_diagnostics.py | 5 +++++ 8 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 tests/typecheck_function_multi_bad.claro create mode 100644 tests/typecheck_function_multi_good.claro diff --git a/CHANGELOG.md b/CHANGELOG.md index d02e037..ea3714c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.18.26-dev multi-parameter function diagnostics + +- Extended the function-argument typecheck foundation so both `DO` and compatibility `CALL ... WITH` calls can report checked parameter mismatches. +- Added multi-parameter positive and negative fixtures that verify each wrong argument gets a clear parameter-specific diagnostic. +- Included the function argument fixtures in `claro validate` so package validation covers the diagnostic foundation directly. + ## v1.18.26-dev typed function diagnostic foundation - Added a narrow `claro typecheck` foundation for function argument diagnostics: if a function body declares a parameter expectation with `CHECK TYPE parameter IS TYPE`, calls to that function are checked against the expected argument type. diff --git a/README.md b/README.md index a7fcb6c..eb9e6b4 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,17 @@ DO square "oops" Type mismatch for function square: parameter amount needs NUMBER, but this argument looks like TEXT. ``` +For functions with more than one checked parameter, Claro reports each mismatched argument with the parameter name: + +```claro +TEACH label TAKES name, age + CHECK TYPE name IS TEXT + CHECK TYPE age IS NUMBER +END + +CALL label WITH 7, "old" +``` + ## Project and package workflow v1.18.26 hardens Claro's project/package workflow. diff --git a/docs/ADVANCED_STATIC_TYPING.md b/docs/ADVANCED_STATIC_TYPING.md index d1f11b6..1e1b7dd 100644 --- a/docs/ADVANCED_STATIC_TYPING.md +++ b/docs/ADVANCED_STATIC_TYPING.md @@ -73,6 +73,26 @@ Output: Type mismatch for function square: parameter amount needs NUMBER, but this argument looks like TEXT. ``` +Multiple checked parameters are reported separately, so a learner can fix each argument one at a time: + +```claro +TEACH label TAKES name, age + CHECK TYPE name IS TEXT + CHECK TYPE age IS NUMBER + SAY name + SAY age +END + +CALL label WITH 7, "old" +``` + +Output: + +```text +Type mismatch for function label: parameter name needs TEXT, but this argument looks like NUMBER. +Type mismatch for function label: parameter age needs NUMBER, but this argument looks like TEXT. +``` + ## Status -This is currently a static checker feature. It improves `claro typecheck` and validation confidence. Runtime enforcement for every container mutation and richer function signatures can be added later after the syntax is classroom-tested. +This is currently a static checker feature. It improves `claro typecheck` and validation confidence for `DO` and compatibility `CALL ... WITH` function calls. Runtime enforcement for every container mutation and richer function signatures can be added later after the syntax is classroom-tested. diff --git a/docs/CURRENT_STATUS.md b/docs/CURRENT_STATUS.md index 6ee8d03..39e8876 100644 --- a/docs/CURRENT_STATUS.md +++ b/docs/CURRENT_STATUS.md @@ -52,7 +52,7 @@ Ready now: - typed variables such as `SET score NUMBER 10` - `TYPE OF` and `CHECK TYPE` - typed list/map checks through `claro typecheck` -- a narrow function argument check: `CHECK TYPE parameter IS TYPE` inside a function lets `claro typecheck` catch mismatched call arguments +- a narrow function argument check: `CHECK TYPE parameter IS TYPE` inside a function lets `claro typecheck` catch mismatched `DO` and `CALL ... WITH` arguments, including multiple checked parameters Still needed: - richer typed function signatures and return values diff --git a/src/claro.c b/src/claro.c index 8a814b6..7589ba5 100644 --- a/src/claro.c +++ b/src/claro.c @@ -523,7 +523,7 @@ static int typecheck_file(const char *path){ FILE *f=fopen(path,"rb"); char line else if(!strcmp(up,"ASK")){ const char *as=find_word_ci(t,"AS"); char *name=NULL,*type=NULL; if(as){ const char *pcur=as+2; name=unquote_token(&pcur); { char *rest=xstrdup(trim_inplace((char*)pcur)); if(claro_is_type_word(rest)) type=rest; else free(rest); } } else { const char *pcur=t+3; char *prompt=unquote_token(&pcur); free(prompt); name=unquote_token(&pcur); { char *rest=xstrdup(trim_inplace((char*)pcur)); if(claro_is_type_word(rest)) type=rest; else free(rest); } } if(name&&*trim_inplace(name)) type_env_set(&types,trim_inplace(name),type?type:"TEXT"); free(name); free(type); } else if(!strcmp(up,"TYPE")&&starts_ci(t,"TYPE OF")){ char *name=check_var_after_as(t); if(name){ type_env_set(&types,name,"TEXT"); free(name); } } else if(!strcmp(up,"NEW")){ const char *as=find_word_ci(t,"AS"); char *name=NULL; if(as) name=xstrdup(trim_inplace((char*)as+2)); else { const char *pcur=t+3; char *cls=unquote_token(&pcur); free(cls); name=unquote_token(&pcur); } if(name&&*trim_inplace(name)) type_env_set(&types,trim_inplace(name),"OBJECT"); free(name); } - else if(!strcmp(up,"DO")&&!find_word_ci(t,"TIMES")){ const char *pcur=t+2; char *fname=unquote_token(&pcur); char **parts=NULL; int ac=0,i; if(*trim_inplace((char*)pcur)) ac=split_args(pcur,&parts); for(i=0;i=argc) return 0; if(strcmp(argv[arg],"help")==0||strcmp(argv[arg],"--help")==0){ print_help(); return 0; } if(strcmp(argv[arg],"test")==0) return run_tests(); if(strcmp(argv[arg],"repl")==0) return run_repl(); if(strcmp(argv[arg],"examples")==0) return show_examples(); if(strcmp(argv[arg],"doctor")==0) return run_doctor(); if(strcmp(argv[arg],"validate")==0) return run_validate(); if(strcmp(argv[arg],"package")==0) return run_package_cmd(argc,argv,arg+1); if(strcmp(argv[arg],"ide")==0) return print_ide_info(); if(strcmp(argv[arg],"new")==0&&arg+1=argc){ Runtime rt; int rc; char *mainfile=project_value("main"); if(!mainfile||!*mainfile){ if(mainfile) free(mainfile); mainfile=xstrdup("main.claro"); } rt_init(&rt); rt.trace=trace; rt.script_argc=0; rt.script_argv=NULL; rc=run_file(&rt,mainfile); free(mainfile); return rc; } } { Runtime rt; int rc; rt_init(&rt); rt.trace=trace; rt.script_argc=argc-arg-1; rt.script_argv=argv+arg+1; rc=run_file(&rt,argv[arg]); return rc; } } diff --git a/tests/typecheck_function_multi_bad.claro b/tests/typecheck_function_multi_bad.claro new file mode 100644 index 0000000..467d029 --- /dev/null +++ b/tests/typecheck_function_multi_bad.claro @@ -0,0 +1,8 @@ +TEACH label TAKES name, age + CHECK TYPE name IS TEXT + CHECK TYPE age IS NUMBER + SAY name + SAY age +END +CALL label WITH "Ada", 12 +CALL label WITH 7, "old" diff --git a/tests/typecheck_function_multi_good.claro b/tests/typecheck_function_multi_good.claro new file mode 100644 index 0000000..95a13be --- /dev/null +++ b/tests/typecheck_function_multi_good.claro @@ -0,0 +1,8 @@ +TEACH label TAKES name, age + CHECK TYPE name IS TEXT + CHECK TYPE age IS NUMBER + SAY name + SAY age +END +CALL label WITH "Ada", 12 +DO label "Grace", 9 diff --git a/tools/validate_typecheck_diagnostics.py b/tools/validate_typecheck_diagnostics.py index d39ca4e..f09f51f 100644 --- a/tools/validate_typecheck_diagnostics.py +++ b/tools/validate_typecheck_diagnostics.py @@ -19,10 +19,15 @@ EXPECTED = { "tests/typecheck_function_bad.claro": [ "tests/typecheck_function_bad.claro:5: Type mismatch for function square: parameter amount needs NUMBER, but this argument looks like TEXT.", ], + "tests/typecheck_function_multi_bad.claro": [ + "tests/typecheck_function_multi_bad.claro:8: Type mismatch for function label: parameter name needs TEXT, but this argument looks like NUMBER.", + "tests/typecheck_function_multi_bad.claro:8: Type mismatch for function label: parameter age needs NUMBER, but this argument looks like TEXT.", + ], } EXPECTED_OK = [ "tests/typecheck_function_good.claro", + "tests/typecheck_function_multi_good.claro", ] STALE_PHRASES = [