CS 541 Lecture -*- Outline -*- * Semantics of Object-Oriented Languages ** Semantics of Message passing *** Objects are records (environments) with functional fields but only operation is "message sending" ---------- aStack = [elems |-> (allocate-location nil), push |-> \self. \i. update(self.elems, cons((value self.elems), i)), pop |-> \self. update(self.elems, (tl (value self.elems))), top |-> \self. (hd (value self.elems))] ---------- the "value" part distinguishes between l and r-values. so domain equation is something like Object = MessageName -> (Procedure + Unbound) *** Message passing is field selection and invocation ---------------------- valE[[ (send E M) ]] = \u. let o = (valE[[E]]u) in cases o . [[M]] of isProcedure(p) -> (p o) else error end ---------------------- the value o is passed as the value of "self" ** Semantics of Inheritance a la William Cook (1989) (compare to Cardelli) key is modification of self reference client --> P -\ ^ | self reference \__| client --> M --> P -\ ^ | inheritance \________| *** idea: inheritance for generators idea implict in Cook's semantics, example from T.B. Dinesh generator for factorial ------------- fact = fix F, where F := \f . \n . (n equals 0) -> 1 [] (n times (f (n minus 1))) fact = (fix F) = <(fix F) is a fixed point of F> (F (fix F)) = \n . (n equals 0) -> 1 [] (n times ((fix F) (n minus 1))) ------------- want to modify fact so that it returns 3 for argument of 3: ---------------- fact' = \n . (n equals 3) -> 3 [] (fact n) ---------------- but fact' 4 = 24, recursions don't go through fact' ---------------- fact'' = fix (G o F), where G := \g . \n . (n equals 3) -> 3 [] (g n) fact'' = (fix (G o F)) = <(fix (G o F)) is a fixed point of G composed with F> ((G o F) (fix (G o F))) = G (F (fix (G o F))) = G (\n . (n equals 0) -> 1 [] (n times ((fix (G o F)) (n minus 1)))) = \n . (n equals 3) -> 3 [] ((\n . (n equals 0) -> 1 [] (n times ((fix (G o F)) (n minus 1)))) n) = \n . (n equals 3) -> 3 [] ((n equals 0) -> 1 [] (n times ((fix (G o F)) (n minus 1)))) ---------------- conclusions: by using generators, we can modify recursive functions basic idea of the semantics of inheritance below may be useful in other contexts. *** Record Combination functions (formalize modification of records) fields conflict if have labels in common record combination function is a binary function on records left preferential (m(+)n)(s) = m(s) if s in dom(m) = n(s) otherwise compare [ x|-> 1 ] (+) r and r[x|->1] so this is similar to traditional env extension. strict (m(strict)n)(s) = \bot if s in both dom(m) and dom(n) = (m\cup n)(s) otherwise *** Generators (functionals used to describe fixed points) are functions used to specify fixed points, whose formal parameter represents self-refernce G1 = \self. [ base |-> 7, square |-> self.base * self.base] can use to define objects by fixed-point operator: fix(G1) = [base |-> 7, square |-> 49] *** Inheritance using generators Inheritance is derivation of new generator from existing generators in such a way that the formal parameter of the derived generator is passed to all inherited generators. **** Distributative combination G [*] H = \self.(G(self) * H(self)) [(+)] let G2 = \self.[base |-> 2] G2 [(+)] G1 = \self. G2(self) (+) G1(self) = \self. [base |-> 2, square |-> self.base * self.base] note that fix(G2 [(+)] G1) = [base |-> 2, square |-> 4] [.] distributitive application function where . is function application: f . x = f(x) W [.] G = \self . W(self)(G(self)) **** Wrappers a function designed to modify a self-referntial structure in a self-referential way; has two parameters one is self-reference (self) other is the superstructure being modified (super) looks like \self.\super. body(self,super) client --> W -super-> G ^ | | self /__v__________v self **** Record Inheritance distributive form of operator w |> p = (w . p) (+) p = w(p) (+) p ____________ | Parent | | | -->| self---| | | | | (+) | |____________| |______> | / |____________ / ___________ | / | Wrapper | | / | super - / | | / | self--/ |___________| W [|>] P = (W [.] P) [(+)] P makes it possible for the wrapper to access the parent and for modification and self reference can be generalized to multiple inheritance. *** Example (from Cook 89) ---------- ; generator that is denotation of class Point Point(a,b) = \self . [ x |-> a, y |-> b, distFromOrig |-> sqrt(square(self.x) + square(self.y)), closerToOrig |-> \p. (self.distFromOrig < p.distFromOrig)] ---------- instance is created by taking a fixed-point: myPoint = fix(Point(3,4)) = [ x |-> 3, y |-> 4, distFromOrig |-> 5, closerToOrig |-> \p. (5 < p.distFromOrig)] ------------ class Circle(a,b,r) inherit Point(a,b) method radius = r method distFromOrig = max(0, super.distFromOrig - self.radius) ; wrapper that is used to give denotation of the above class CircleWrapper(a,b,r) = \self . \super . [ radius |-> r, distFromOrig |-> max(0, super.distFromOrig - self.radius)] ; denotation of the above class Circle(a,b,r) = CircleWrapper(a,b,r) [|>] Point(a,b) = (CircleWrapper(a,b,r) [.] Point(a,b)) [(+)] Point(a,b) = (\self . (CircleWrapper(a,b,r)(self))(Point(a,b)(self))) [(+)] Point(a,b) = \self . (\self . (CircleWrapper(a,b,r)(self))(Point(a,b)(self)))(self) (+) (Point(a,b))(self) = \self. [ x |-> a, y |-> b, radius |-> r, distFromOrig |-> max(0, sqrt(square(self.x) + square(self.y)) - self.radius), closerToOrig |-> \p. (self.distFromOrig < p.distFromOrig)] ------------ ** Conclusions denotational understanding allows one to design new features: e.g., function inheritance (modify recursive calls) compositional semantics of inheritance (not based on syntax)