smalltalk: Object>>becomeForward: + 6 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-25 09:54:40 +00:00
parent 3e83624317
commit fdd8e18cc3
3 changed files with 83 additions and 1 deletions

View File

@@ -565,6 +565,24 @@
(cond
((not (st-class-ref? arg)) false)
(else (= target-cls (get arg :name))))))
;; Object>>becomeForward: aReceiver — one-way become. The receiver's
;; class and ivars are mutated in place to match the target. Every
;; existing reference to the receiver dict sees the new identity.
;; Note: receiver and target remain distinct dicts (not == in the
;; SX-identity sense), but receiver behaves as though it were the
;; target — which is the practical Pharo guarantee.
((= selector "becomeForward:")
(let ((other (nth args 0)))
(cond
((not (st-instance? receiver))
(error "becomeForward: only supported on user instances"))
((not (st-instance? other))
(error "becomeForward: target must be a user instance"))
(else
(begin
(dict-set! receiver :class (get other :class))
(dict-set! receiver :ivars (get other :ivars))
receiver)))))
((or (= cls "SmallInteger") (= cls "Float"))
(st-num-send receiver selector args))
((or (= cls "String") (= cls "Symbol"))

View File

@@ -239,3 +239,66 @@
(evp "Cat compile: 'taggedMethod ^ #yes' classified: 'demo'")
(str (evp "^ Cat new taggedMethod")))
"yes")
;; ── 19. Object>>becomeForward: ──
(st-class-define! "Box" "Object" (list "value"))
(st-class-add-method! "Box" "value" (st-parse-method "value ^ value"))
(st-class-add-method! "Box" "value:" (st-parse-method "value: v value := v. ^ self"))
(st-class-add-method! "Box" "kind" (st-parse-method "kind ^ #box"))
(st-class-define! "Crate" "Object" (list "value"))
(st-class-add-method! "Crate" "value" (st-parse-method "value ^ value"))
(st-class-add-method! "Crate" "value:" (st-parse-method "value: v value := v. ^ self"))
(st-class-add-method! "Crate" "kind" (st-parse-method "kind ^ #crate"))
(st-test "before becomeForward: instance reports its class"
(str (evp "^ (Box new value: 1) class name"))
"Box")
(st-test "becomeForward: changes the receiver's class"
(evp
"| a b |
a := Box new value: 1.
b := Crate new value: 99.
a becomeForward: b.
^ a class name")
"Crate")
(st-test "becomeForward: routes future sends through new class"
(evp
"| a b |
a := Box new value: 1.
b := Crate new value: 99.
a becomeForward: b.
^ a kind")
(make-symbol "crate"))
(st-test "becomeForward: takes target's ivars"
(evp
"| a b |
a := Box new value: 1.
b := Crate new value: 99.
a becomeForward: b.
^ a value")
99)
(st-test "becomeForward: leaves the *target* instance unchanged"
(evp
"| a b |
a := Box new value: 1.
b := Crate new value: 99.
a becomeForward: b.
^ b kind")
(make-symbol "crate"))
(st-test "every reference to the receiver sees the new identity"
(evp
"| a alias b |
a := Box new value: 1.
alias := a.
b := Crate new value: 99.
a becomeForward: b.
^ alias kind")
(make-symbol "crate"))
(list st-test-pass st-test-fail)