Migrate example value classes from Object to Value subclass#1028
Migrate example value classes from Object to Value subclass#1028
Conversation
- SchemeSymbol, SchemeLambda: Object → Value subclass, drop manual getters and custom =:= (auto-generated by Value) - Message, Transaction: Object → Value subclass, rename get* accessors to field names (text, sender, amount, from, to, status, timestamp) and update tests accordingly - Refactor eval.bt special-form dispatch to match: expression via extracted evalSpecialOrApply:tail:in: helper method Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review infoConfiguration used: Organization UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR converts several example classes from Object to Value subclasses (bank, chat-room, SICP), removes explicit getter methods in favor of auto-generated accessors and keyword constructors, updates tests to use new accessors, and refactors the Scheme evaluator by extracting special-form dispatch and application into dedicated methods. Changes
Sequence Diagram(s)sequenceDiagram
actor Caller
participant SchemeEval
participant Env
participant Proc as Procedure
Caller->>SchemeEval: evalSpecialOrApply(head, tail, env)
alt head is special-form
SchemeEval->>SchemeEval: handle special (quote/define/lambda/if/cond/let/and/or)
SchemeEval-->>Caller: return value
else not special
SchemeEval->>SchemeEval: evalApply(head, tail, env)
SchemeEval->>Env: evaluate head -> procedure value
Env-->>SchemeEval: procedure (Proc)
SchemeEval->>Proc: evaluate args in env
Proc-->>SchemeEval: result
SchemeEval-->>Caller: return result
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR updates several example-domain “record” classes to be explicit immutable value objects by migrating them from Object subclass: to Value subclass: (per ADR 0042), and refactors the SICP Scheme evaluator’s special-form dispatch to use pattern matching.
Changes:
- Migrate
SchemeSymbol,SchemeLambda,Message, andTransactiontoValue subclass:and remove now-redundant manual getters / custom equality. - Rename
Message/Transactionget*accessors to idiomatic field-name accessors (auto-generated byValue) and update example tests accordingly. - Refactor
SchemeEvalspecial-form dispatch into amatch:expression viaevalSpecialOrApply:tail:in:.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| examples/sicp/src/scheme/symbol.bt | Convert SchemeSymbol to a Value type; rely on auto-generated accessor/equality; update doc examples. |
| examples/sicp/src/scheme/lambda.bt | Convert SchemeLambda to a Value type and rely on auto-generated accessors. |
| examples/sicp/src/scheme/eval.bt | Replace repeated special-form if-chains with match: dispatch via evalSpecialOrApply:tail:in:. |
| examples/chat-room/src/message.bt | Convert Message to Value subclass: and remove manual get* accessors; update docs. |
| examples/chat-room/test/message_test.bt | Update tests to use text/sender accessors. |
| examples/bank/src/transaction.bt | Convert Transaction to Value subclass: and remove manual get* accessors; update docs. |
| examples/bank/test/transaction_test.bt | Update tests to use amount/from/to/status/timestamp accessors. |
Addresses Copilot review: function-application logic was duplicated between eval:in: (non-symbol head) and the _ arm of evalSpecialOrApply:tail:in: (non-special-form symbol). Extracted into evalApply:tail:in: so argument evaluation rules live in one place. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@examples/chat-room/src/message.bt`:
- Around line 7-17: The Message type was changed to a Value subclass which
violates the file-specific rule requiring Object subclass with new: construction
semantics; revert Message to "Object subclass: Message" (not Value) and update
the example usage and documentation to use the Object/new: constructor pattern
(e.g., create via new: or whatever the project's Object API uses) instead of the
Value-style literal constructor; ensure the class declaration and the usage
examples/description (mentions of auto-generated getters, immutability lines)
consistently reflect Message as an Object subclass using new: semantics.
In `@examples/sicp/src/scheme/eval.bt`:
- Line 108: Remove the leading caret from the final expression "^sym match:" so
the method ends with an implicit return; locate the expression "^sym match:" in
the method and change "^sym match:" to "sym match:" (keeping the rest of the
expression unchanged) and ensure ^ is only used elsewhere for early returns per
Beamtalk guidelines.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
examples/bank/src/transaction.btexamples/bank/test/transaction_test.btexamples/chat-room/src/message.btexamples/chat-room/test/message_test.btexamples/sicp/src/scheme/eval.btexamples/sicp/src/scheme/lambda.btexamples/sicp/src/scheme/symbol.bt
There was a problem hiding this comment.
♻️ Duplicate comments (2)
examples/sicp/src/scheme/eval.bt (2)
104-106:⚠️ Potential issue | 🟡 MinorRemove
^from the method’s final expression.Line 106 uses
^on the terminalmatch:expression; this should be an implicit return.✂️ Suggested fix
- ^sym match: [ + sym match: [As per coding guidelines
**/*.bt: “Use^ONLY for early returns in Beamtalk, never on last expression.”🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/sicp/src/scheme/eval.bt` around lines 104 - 106, In evalSpecialOrApply (method header: evalSpecialOrApply: head tail: tail in: env =>) remove the caret prefix on the final expression so the terminal "sym match: [...]" is returned implicitly; ensure no other early-return uses of ^ are removed, only the trailing ^ before the match expression should be deleted to comply with the guideline that ^ is used only for early returns.
108-149:⚠️ Potential issue | 🟠 MajorAdd arity/shape checks for special forms before indexing
tail.
quote/define/lambda/if/letcurrently calltail first/tail at:directly. Malformed input can surface raw index/type failures instead of evaluator-grade messages.🛡️ Suggested validation pattern
- "quote" -> tail first; + "quote" -> [ + tail size =:= 1 ifFalse: [self error: "quote expects exactly 1 argument"] + tail first] value; @@ "define" -> [ + tail size =:= 2 ifFalse: [self error: "define expects exactly 2 arguments"] + ((tail at: 1) class =:= SchemeSymbol) ifFalse: [ + self error: "define expects a symbol name as first argument"] varName := (tail at: 1) name defVal := self eval: (tail at: 2) in: env env define: varName value: defVal. nil] value; @@ "lambda" -> [ + tail size =:= 2 ifFalse: [self error: "lambda expects parameters and body"] + ((tail at: 1) class =:= List) ifFalse: [ + self error: "lambda expects a parameter list"] params := (tail at: 1) collect: [:p | p name] SchemeLambda withParams: params body: (tail at: 2) env: env] value; @@ "if" -> [ + ((tail size =:= 2) or: [tail size =:= 3]) ifFalse: [ + self error: "if expects 2 or 3 arguments"] condVal := self eval: (tail at: 1) in: env @@ "let" -> [ + tail size =:= 2 ifFalse: [self error: "let expects bindings and body"] + ((tail at: 1) class =:= List) ifFalse: [ + self error: "let expects a bindings list"] binds := tail at: 1As per coding guidelines
examples/sicp/src/scheme/eval.bt: “Error handling should provide clear, user-friendly error messages (e.g., 'Not a procedure: X') instead of raw system crashes”.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/sicp/src/scheme/eval.bt` around lines 108 - 149, The special-form branches in the evaluator (the dispatch that matches "quote", "define", "lambda", "if", "let" and then uses tail first/at:) lack arity/type checks and can raise raw index/type errors; update each branch (the handlers for "quote", "define", "lambda", "if", "let" inside the eval dispatch and the helper methods evalCond/evalAnd/evalOr/evalApply as appropriate) to first validate tail is a non-nil sequence of the expected length and shapes (e.g., "define" must have exactly 2 operands and first operand must be a symbol name, "lambda" must have a parameter list and a body, "if" must have 2 or 3 operands, "let" must have a bindings list and a body, "quote" must have one operand) and when validation fails raise a clear evaluator error message (e.g., "Malformed define: expected (define name expr)") instead of letting index/type exceptions surface.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@examples/sicp/src/scheme/eval.bt`:
- Around line 104-106: In evalSpecialOrApply (method header: evalSpecialOrApply:
head tail: tail in: env =>) remove the caret prefix on the final expression so
the terminal "sym match: [...]" is returned implicitly; ensure no other
early-return uses of ^ are removed, only the trailing ^ before the match
expression should be deleted to comply with the guideline that ^ is used only
for early returns.
- Around line 108-149: The special-form branches in the evaluator (the dispatch
that matches "quote", "define", "lambda", "if", "let" and then uses tail
first/at:) lack arity/type checks and can raise raw index/type errors; update
each branch (the handlers for "quote", "define", "lambda", "if", "let" inside
the eval dispatch and the helper methods evalCond/evalAnd/evalOr/evalApply as
appropriate) to first validate tail is a non-nil sequence of the expected length
and shapes (e.g., "define" must have exactly 2 operands and first operand must
be a symbol name, "lambda" must have a parameter list and a body, "if" must have
2 or 3 operands, "let" must have a bindings list and a body, "quote" must have
one operand) and when validation fails raise a clear evaluator error message
(e.g., "Malformed define: expected (define name expr)") instead of letting
index/type exceptions surface.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
examples/sicp/src/scheme/eval.bt
Per CLAUDE.md: use ^ only for early returns, never on last expression. `sym match: [...]` is the method's final expression — implicit return suffices. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Re CodeRabbit comments:
|
Summary
SchemeSymbol,SchemeLambda,Message, andTransactionfromObject subclass:toValue subclass:, making immutability intent explicit per ADR 0042Valueauto-generatesget*accessors onMessage/Transactionto bare field names (text,sender,amount, etc.) — idiomatic Beamtalk style — with matching test updatesSchemeEval's special-form string dispatch from 8 repeated(sym =:= "x") ifTrue:chains into amatch:expression via an extractedevalSpecialOrApply:tail:in:helperTest plan
just buildpassesjust clippypassescargo run --bin beamtalk -- build examples/sicp/compiles cleancargo run --bin beamtalk -- test examples/sicp/passes (one pre-existing doc-test failure unrelated to this change)just test— 649 BUnit + 2208 runtime tests all green🤖 Generated with Claude Code
Summary by CodeRabbit
Refactor
Tests