typecheck: reject extra AS TO field tokens

This commit is contained in:
Hermes Agent
2026-09-21 07:27:18 +00:00
parent aae8eb7608
commit 72a5589a3e
7 changed files with 29 additions and 1 deletions
+11
View File
@@ -825,6 +825,17 @@ SET player.score AS NUMBER TO 10
Both explicit forms must agree with the class field declaration.
The separated form accepts one value expression only. Extra words are rejected
with a repair hint instead of being silently ignored:
```claro
SET player.score AS NUMBER TO 10 extra
```
```text
SET player.score has extra text after value 10. Keep only the field name, type, TO, and one expression.
```
The `AS ... TO` spelling also works inside modern and compatibility object methods:
```claro
+1
View File
@@ -83,6 +83,7 @@ Ready now:
- object creation now rejects repeated object names with a direct repair hint, so two `NEW Player player` statements cannot silently replace one another during type checking; when a script declares at least one class, a misspelled `NEW` class name gets a direct declaration hint without changing the older permissive no-class form; a missing class name or object name gets a direct example repair; extra words after the object name get a direct repair hint instead of being silently ignored
- a narrow object-field assignment/check-type check for simple `NEW Class object` plus direct `SET object.field value` and `CHECK TYPE object.field IS TYPE` cases when the class declares `HAS field TYPE`; validation now covers correct NUMBER, TEXT, and YESNO direct assignments, dedicated positive and explicitly typed NUMBER/TEXT field assignments, explicitly typed method-body assignments to undeclared fields with a `HAS field TYPE` repair hint in modern and compatibility method syntax, dedicated positive NUMBER/TEXT/YESNO `CHECK TYPE` metadata fixtures, simple and chained object aliases for both field assignments and `CHECK TYPE` metadata (including a chained TEXT-field check), aliased object-method calls including chained aliases in modern `DO` and compatibility `CALL ... WITH` forms (with a dedicated positive modern `DO` chained-alias fixture), field-to-field, compound arithmetic field expressions, and arithmetic/text expression result types, negative NUMBER/TEXT/YESNO field `CHECK TYPE` metadata mismatches, NUMBER/TEXT/YESNO-expectation unknown-field `CHECK TYPE` diagnostics, missing-object field assignment and `CHECK TYPE` diagnostics, NUMBER/TEXT/YESNO wrong-type diagnostics, field collection when a `HAS` field appears after a simple method, NUMBER/TEXT/YESNO-valued unknown-field diagnostics for direct assignments to undeclared fields including explicitly typed assignments, numeric and text results from simple arithmetic/text expressions in object-field assignments, plus method-body field assignment and `CHECK TYPE` diagnostics for NUMBER, TEXT, and YESNO fields in modern and compatibility syntax, including compatibility YESNO `CHECK TYPE` metadata coverage, direct method assignments to undeclared fields now produce a beginner-facing missing-field diagnostic when the assigned expression has a known type, and a plain beginner-facing unknown-field diagnostic when the assigned expression is not inferable yet in both modern and compatibility method syntax; method-body `CHECK TYPE` now reports an unknown field with a repair hint in both method syntaxes, including compatibility `TAKES` / `LEARNED` methods; explicitly typed assignments to declared method fields now validate the class-declared field type instead of trusting only the inline type annotation, so a wrong value such as `SET score TEXT \"oops\"` reports the method and field in the diagnostic.
- inline method-field annotations are checked against the class `HAS` declaration in modern and compatibility methods; conflicting known types and unknown annotation names produce field-specific repair guidance, with positive and negative focused fixtures for both syntaxes.
- direct object-field `AS ... TO` assignments reject extra words after the value with a repair hint, so `SET player.score AS NUMBER TO 10 extra` cannot silently ignore the trailing text.
- Direct object-field validation also has positive coverage for explicit `NUMBER`, `TEXT`, and `YESNO` annotations, such as `SET player.ready YESNO YES`, plus the compatibility-shaped `AS ... TO` form such as `SET player.score AS NUMBER TO 10`, while the shorter unannotated form remains supported; method-body field assignments have matching positive coverage for both modern and compatibility `TEACH` forms using `SET score AS NUMBER TO 10`, and those two `AS ... TO` method fixtures are now included in `claro validate`; conflicting annotations such as `SET player.score TEXT "oops"` explain the class-declared type and how to repair it, and unknown annotations such as `SET player.score AS BANANA TO 10` or `SET player.score BANANA 10` identify the invalid type and suggest the declared field type.
Still needed:
+1
View File
@@ -52,6 +52,7 @@ Keep declared return types honest: `claro typecheck` now reports friendly diagno
8d.1. Keep direct field annotation forms balanced: the compatibility-shaped `SET player.score AS NUMBER TO 10` form now has a dedicated positive fixture beside short explicit annotations, so both accepted spellings remain protected by focused validation.
8d.2. Keep method field annotation forms balanced: modern and compatibility methods now have dedicated positive fixtures for `SET score AS NUMBER TO 10`, so the compatibility-shaped annotation remains protected inside both supported method syntaxes.
8d.3. Keep release validation aligned with method annotation coverage: the modern and compatibility `AS ... TO` method fixtures now run through `claro validate`, not only the focused Python diagnostic validator.
8d.4. Keep separated direct field assignments unambiguous: `SET player.score AS NUMBER TO 10 extra` now reports the trailing text and explains the one-expression form instead of accepting a partially parsed value.
8e. Keep inline method-field annotation coverage aligned across syntax generations: compatibility `TAKES` / `LEARNED` methods now have matching positive and negative fixtures, so older lessons retain the same class-declared-type guidance.
8f. Keep inline method-field annotations learner-facing: an unknown annotation such as `BANANA` now names the field and method and suggests the `HAS` type instead of silently treating the annotation as an expression.
8g. Keep unknown inline method-field annotation diagnostics aligned across syntax generations: compatibility `TAKES` / `LEARNED` methods now have matching focused coverage for misspelled annotations.
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -57,6 +57,12 @@ class ValidateTypecheckDiagnosticsTests(unittest.TestCase):
MODULE.EXPECTED_OK,
)
def test_includes_as_to_typed_field_extra_tokens_fixture(self):
self.assertIn(
"tests/typecheck_object_field_typed_as_to_extra_tokens_bad.claro",
MODULE.EXPECTED,
)
def test_includes_as_to_method_field_success_fixtures(self):
self.assertIn(
"tests/typecheck_method_inline_field_annotation_as_to_good.claro",
@@ -0,0 +1,6 @@
CLASS Player
HAS score NUMBER
END
NEW Player player
SET player.score AS NUMBER TO 10 extra
+3
View File
@@ -260,6 +260,9 @@ EXPECTED = {
"tests/typecheck_object_field_typed_conflict_bad.claro": [
"tests/typecheck_object_field_typed_conflict_bad.claro:6: Type mismatch for field player.score: class declares NUMBER, but this assignment says TEXT. Use NUMBER for score.",
],
"tests/typecheck_object_field_typed_as_to_extra_tokens_bad.claro": [
"tests/typecheck_object_field_typed_as_to_extra_tokens_bad.claro:6: SET player.score has extra text after value 10. Keep only the field name, type, TO, and one expression.",
],
"tests/typecheck_object_field_typed_unknown_type_bad.claro": [
"tests/typecheck_object_field_typed_unknown_type_bad.claro:6: Field player.score needs a known type such as NUMBER, TEXT, or YESNO, but BANANA is not a Claro type. Use NUMBER for score.",
],