smalltalk: super send + top-level temps + 9 super tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -296,20 +296,41 @@
|
||||
((st-class-ref? v) "Class")
|
||||
(else (st-class-of v)))))
|
||||
|
||||
;; super send: lookup starts at the *defining* class's superclass, not the
|
||||
;; receiver class. This is what makes inherited methods compose correctly
|
||||
;; under refinement — a method on Foo that calls `super bar` resolves to
|
||||
;; Foo's superclass's `bar` regardless of the dynamic receiver class.
|
||||
(define
|
||||
st-super-send
|
||||
(fn
|
||||
(receiver selector args defining-class)
|
||||
(let
|
||||
((super (st-class-superclass defining-class)))
|
||||
(cond
|
||||
((= super nil)
|
||||
(error (str "super send past Object: " selector)))
|
||||
(else
|
||||
(let ((method (st-method-lookup super selector false)))
|
||||
(cond
|
||||
((not (= method nil)) (st-invoke method receiver args))
|
||||
(else (st-primitive-send receiver selector args)))))))))
|
||||
(cond
|
||||
((= defining-class nil)
|
||||
(error (str "super send outside method context: " selector)))
|
||||
(else
|
||||
(let
|
||||
((super (st-class-superclass defining-class))
|
||||
(class-side? (st-class-ref? receiver)))
|
||||
(cond
|
||||
((= super nil)
|
||||
(error (str "super send past root: " selector " in " defining-class)))
|
||||
(else
|
||||
(let ((method (st-method-lookup super selector class-side?)))
|
||||
(cond
|
||||
((not (= method nil))
|
||||
(st-invoke method receiver args))
|
||||
(else
|
||||
;; Try primitives starting from super's perspective too —
|
||||
;; for native receivers the primitive table is global, so
|
||||
;; super basically reaches the same primitives. The point
|
||||
;; of super is to skip user overrides on the receiver's
|
||||
;; class chain below `super`, which method-lookup above
|
||||
;; already enforces.
|
||||
(let ((p (st-primitive-send receiver selector args)))
|
||||
(cond
|
||||
((= p :unhandled)
|
||||
(st-dnu receiver selector args))
|
||||
(else p)))))))))))))
|
||||
|
||||
;; ── Method invocation ──────────────────────────────────────────────────
|
||||
(define
|
||||
@@ -689,7 +710,13 @@
|
||||
(src)
|
||||
(let
|
||||
((ast (st-parse src)) (frame (st-make-frame nil nil nil)))
|
||||
(let ((result (smalltalk-eval-ast ast frame)))
|
||||
(cond
|
||||
((st-return-marker? result) (get result :value))
|
||||
(else result))))))
|
||||
(begin
|
||||
(when
|
||||
(and (dict? ast) (has-key? ast :temps))
|
||||
(for-each
|
||||
(fn (t) (dict-set! (get frame :locals) t nil))
|
||||
(get ast :temps)))
|
||||
(let ((result (smalltalk-eval-ast ast frame)))
|
||||
(cond
|
||||
((st-return-marker? result) (get result :value))
|
||||
(else result)))))))
|
||||
|
||||
Reference in New Issue
Block a user