I. Objects and Classes (7.1) A. ideas, terms 1. simple picture: state, methods ------------------------------------------ OBJECTS AND CLASSES (7.1) A STACK OBJECT ______________________ | top-index [ 2 ] | | | | _________ push! | | | | | |_______| | | | 3 | pop! | |_______| | | | 4 | | | |_______| top | | 2 | | | stk |_______| | | | |______________________| state = instance variables methods (operations) = code that responds to messages instance = object ------------------------------------------ What's the C++ jargon for "instance variable"? For method? What's an object like that we've already seen? 2. classes ------------------------------------------ TWO OBJECTS OF THE SAME CLASS ___________ ___________ | | | | | top-index | | top-index | | [ 1 ] push! | [ 2 ] push! | | | | | _____ | | _____ | | |___| pop! | |___| pop! | |___| | | |_3_| | | |_2_| | | |_4_| | | stk|_7_| top | stk|_2_| top | | | | |___________| |___________| def: an *instance variable* is private to each def: a *class variable* is shared by def: *class* is used to mean: ------------------------------------------ What's the C++ jargon for class variable? 3. message = method name + arguments ------------------------------------------ MESSAGE PASSING ___________ ____________ | | | \ / | __ | | | \ / | | push! | \/ | __ | | | push! 1 | | | |__________| | pop! \ \ \ | | | | | top | | |___________| object ^ message ^ def: A set of objects that behave the same in response to sequences of messages form an ------------------------------------------ What does the message do? What's all this good for? B. syntax ------------------------------------------ NEW SYNTAX FOR OBJECTS AND CLASSES Concrete syntax: ::= | | := | := | method | $ () | simpleinstance | simpleclass ::= & ::= && ::= ( ) | ( ) EXAMPLE ------------------------------------------ ------------------------------------------ EXAMPLE WITH CLASS VARIABLES --> define CellWithStatsClass = simpleclass (callsMade) % class variable (value) % instance variable (initialize = method() &value := 0; getVal = method() begin &&callsMade := add1(&&callsMade); &value end; setVal = method(x) begin &&callsMade := add1(&&callsMade); &value := x end; numCalls = method() &&callsMade ) &&callsMade := 0; --> define o = simpleinstance CellWithStatsClass; --> $setVal(o, 3); --> $getVal(o); ------------------------------------------ C. initialization How does a CellWithStatsClass object get initalized? is that safe? D. interpreter 1. abstract syntax ------------------------------------------ NEW ABSTRACT SYNTAX (define-record i-varref (var)) (define-record c-varref (var)) (define-record i-varassign (var exp)) (define-record c-varassign (var exp)) (define-record meth-app (name rands)) (define-record method (formals body)) (define-record new-simpleinst (class-exp)) (define-record new-simpleclass (c-vars i-vars methdecls init-exp)) ------------------------------------------ 2. domains ------------------------------------------ DOMAINS FOR SECTION 7.1 Environment = -> Denoted-Value Denoted-Value = Cell(Expressed-Value) Expressed-Value = Number + Procedure Procedure = prim-proc + closure Instance = Class = NEW DATA STRUCTURES (define-record instance (define-record class ------------------------------------------ Does the class variable environment need nesting? ------------------------------------------ EXPRESSED VALUE PROCEDURES instance? : (-> (Expressed-Value) boolean) make-instance : (-> (Expressed-Value (vector Denoted-Value)) Expressed-Value) instance->class : (-> (Expressed-Value) Expressed-Value) instance->i-vals : (-> (Expressed-Value) (vector Denoted-Value)) class? : (-> (Expressed-Value) boolean) make-class : (-> ((list symbol) (vector Denoted-Value) (list symbol) Method-Environment) Expressed-Value) class->c-vars : (-> (Expressed-Value) (list symbol)) class->c-vals : (-> (Expressed-Value) (vector Denoted-Value)) class->i-vars : (-> (Expressed-Value) (list symbol)) class->m-env : (-> (Expressed-Value) Method-Environment) ------------------------------------------ ------------------------------------------ MORE EXPRESSED VALUE PROCEDURES open-method->expressed : (-> ((-> ((-> () Expressed-Value)) (-> ((list Expressed-Value)) Expressed-Value))) Expressed-Value) expressed->open-method : (-> (Expressed-Value) (-> ((-> () Expressed-Value)) (-> ((list Expressed-Value)) Expressed-Value))) number->expressed : (-> (number) Expressed-Value) expressed->number : (-> (Expressed-Value) number) procedure->expressed : (-> (Procedure) Expressed-Value) expressed->procedure : (-> (Expressed-Value) Procedure) list->expressed : (-> ((list Expressed-Value)) Expressed-Value) expressed->list : (-> (Expressed-Value) (list Expressed-Value)) void->expressed : (-> (void) Expressed-Value) denoted->expressed : (-> (Denoted-Value) Expressed-Value) expressed->denoted : (-> (Expressed-Value) Denoted-Value) ------------------------------------------ ------------------------------------------ INSTANCE AND CLASS VARIABLE PROCS (7.1.4) (define lookup ;; TYPE: (-> (symbol (list symbol) ;; (vector Denoted-Value)) ;; Expressed-Value) (lambda (var vars vals) (cell-ref (cell-lookup var vars vals)))) (define assign! ;; name changed ;; TYPE: (-> (symbol Expressed-Value ;; (list symbol) ;; (vector Denoted-Value)) ;; void) (lambda (var value vars vals) (cell-set! (cell-lookup var vars vals) value))) ------------------------------------------ How would we have written lookup in chapter 6? ------------------------------------------ MORE INSTANCE AND CLASS VARIABLE PROCS (define cell-lookup ;; TYPE: (-> (symbol (list symbol) ;; (vector Denoted-Value)) ;; Denoted-Value) (lambda (var vars vals) (letrec ((loop ; TYPE:(-> ((list symbol) number) ; Denoted-Value) (lambda (vars c) (cond ((null? vars) (error "Unassigned variable:" var)) ((eq? (car vars) var) (vector-ref vals c)) (else (loop (cdr vars) (- c 1))))))) (loop vars (- (length vars) 1))))) ------------------------------------------ ------------------------------------------ METHOD ENVIRONMENT ADT the-empty-method-env : Method-Environment extend-method-env : (-> ((list symbol) (list Method) Method-Environment) Method-Environment) apply-method-env : (-> (Method-Environment symbol) Method) defined-in-method-env? : (-> (Method-Environment symbol) boolean) ------------------------------------------ ------------------------------------------ DOMAINS FOR METHODS Method-Environment = -> Method Open-Method = Class-Thunk -> Method Class-Thunk = () -> Class Method = {Expressed-Value}* -> Expressed-Value PROCEDURES FOR ACCESSING METHODS (define meth-call ;; TYPE: (-> (symbol Class ;; (list Expressed-Value)) ;; Expressed-Value) (lambda (name class args) (let ((method (meth-lookup name class))) (method args)))) (define meth-lookup ;; TYPE: (-> (symbol Class) Method) (lambda (name class) (apply-method-env (class->m-env class) name))) ------------------------------------------ What's the parameter mechanism used to call methods? How can you tell? Would this allow others? 3. evaluation of expressions ------------------------------------------ EVAL-EXP FOR SECTION 7.1 INSTANCE AND CLASS VARIABLES (define eval-exp ;; TYPE: (-> (parsed-exp Environment ;; (maybe Class) ;; (maybe Instance)) ;; Expressed-Value) (lambda (exp env class inst) (variant-case exp (i-varref (var) (c-varref (var) ;; for you to do (i-varassign (var exp) (c-varassign (var exp) ;; for you ------------------------------------------ ------------------------------------------ THE MAYBE ADT maybe? : (-> (datum) boolean) make-something : (-> (T) (maybe T)) make-nothing : (-> () (maybe T)) maybe-something?: (-> ((maybe T)) boolean) maybe-nothing? : (-> ((maybe T)) boolean) something->value : (-> ((maybe T)) T) maybe-test : (-> ((maybe T) (-> (T) U) (-> () U)) U) ------------------------------------------ ------------------------------------------ METHODS (define eval-exp (lambda (exp env class inst) (variant-case exp ;; ... (method (formals body) (meth-app (name rands) ------------------------------------------ ------------------------------------------ INSTANCE CREATION (define eval-exp (lambda (exp env class inst) (variant-case exp ;; ... ------------------------------------------ ------------------------------------------ AUXILIARY FUNCTIONS FOR INSTANCE CREATION (define make-vals ;; TYPE: (-> ((list symbol)) ;; (vector Denoted-Value)) (lambda (vars) (list->vector (map (lambda (x) (make-cell (number->expressed 0))) vars)))) ------------------------------------------ ------------------------------------------ CLASS CREATION (define eval-exp (lambda (exp env class inst) (variant-case exp ;; ... ------------------------------------------ Can methods be recursive? ------------------------------------------ INITIAL METHOD ENVIRONMENT (define init-meth-env ; corrected ;; TYPE: Method-Environment (extend-method-env '(initialize) (list (lambda (args) (void->expressed (displayln "Not initialized")))) the-empty-method-env)) ------------------------------------------ What does this do? II. inheritance (7.2) A. varieties ------------------------------------------ INHERITANCE (7.2) idea: similar kinds of objects should share Techniques: delegation inheritance Varieties: single multiple ------------------------------------------ If a class has two parents, each with method M, what is done? What if both parents define the same instance variable? B. syntax ------------------------------------------ CONCRETE SYNTAX ::= ... | $ () | simpleinstance | class , | $ ::= & ::= && ::= ( ) | ( ) ::= (super {, }*) ------------------------------------------ ------------------------------------------ EXAMPLE define CellClass = class baseobject, % superclass () % no class variables (value) % instance variable (initialize = method() &value := 0; getVal = method() &value; setVal = method(x) &value := x) 0; % no class var initialization define DebugCellClass = class CellClass, () % no class variables () % no instance variables (setVal = method(x) begin printchar(83); space(); %83=S print(x); newline(); $setVal(super,x) end; getVal = method() begin printchar(71); space(); %71=G let v = $getVal(super) in begin print(v); newline(); v end end ) 0; ------------------------------------------ ------------------------------------------ RUNNING IT --> define myCell = simpleinstance CellClass; --> define myDCell = simpleinstance DebugCellClass; --> $getVal(myCell); --> $getVal(myDCell); --> $setVal(myDCell, 3); --> +($getVal(myDCell), $getVal(myDCell)); ------------------------------------------ C. semantics 1. Conceptual domains and data structures ------------------------------------------ SEMANTICS Domains: Environment = -> Denoted-Value Denoted-Value = Cell(Expressed-Value) Expressed-Value = Number + Procedure + List(Expressed-Value) + Void + Instance + Class + Open-Method Procedure = prim-proc + closure Instance = Class x Vector(Denoted-Value) Class = Open-Method = Class-Thunk -> Method Class-Thunk = () -> Class Method = {Expressed-Value}* -> Expressed-Value Method-Environment = -> Method New data structures for expressed values: (define-record class ------------------------------------------ What has to happen when making up the class vars for a class exp? What has to happen when doing a method call that uses super? 2. super method application ------------------------------------------ EVAL-EXP FOR SECTION 7.2 SUPER METHOD APPLICATION (define eval-exp ;; TYPE: (-> (parsed-exp Environment ;; (maybe Class) ;; (maybe Instance)) ;; Expressed-Value) (lambda (exp env class inst) (variant-case exp ;; ... (super-meth-app (name rands) ------------------------------------------ ------------------------------------------ EVAL-EXP FOR SECTION 7.2 NEW CLASS EXPRESSION (define eval-exp (lambda (exp env class inst) (variant-case exp ; ... (new-class (parent-exp c-vars i-vars methdecls init-exp) ... (let ((parent-class (open-methods (map (lambda (decl) (expressed->open-method (eval-exp (decl->exp decl) env class inst)) methdecls))) ------------------------------------------ ------------------------------------------ ;; NEW CLASS CONTINUED (letrec ((new-class (make-class (make-something parent-class) new-c-vars new-c-vals new-i-vars (extend-method-env (map decl->var methdecls) (map (lambda (open-method) (open-method (lambda () new-class))) open-methods) (ignore (eval-exp init-exp env (make-something new-class) (make-nothing) new-class)))) ------------------------------------------ ------------------------------------------ AUXILIARY FUNCTIONS for 7.2.4 (define make-shared-c-vals ;; TYPE: (-> ((vector Denoted-Value) ;; (list symbol)) ;; (vector Denoted-Value)) (lambda (parent-c-vals c-vars) (list->vector (append (vector->list parent-c-vals) (map (lambda (x) (expressed->denoted (number->expressed 0))) c-vars))))) (define make-vals ;; TYPE: (-> ((list symbol)) ;; (vector Denoted-Value)) (lambda (vars) (list->vector (map (lambda (x) (expressed->denoted (number->expressed 0))) vars)))) ------------------------------------------ 3. some examples ------------------------------------------ MESSAGE PASSING EXAMPLE define Cclass = class baseobject, () () (initialize = method() noop; m1 = method () $m2(self); m2 = method () 3 ) 0; define Dclass = class Cclass, () () (m2 = method () 4 ) 0; define aD = simpleinstance Dclass; --> $m1(aD); ------------------------------------------ what is the result of $m1(aD) ? What if we added another method to D... m3 = method() $m2(super) and then ran $m3(aD) ? What if m2's body was "$m2(self)" instead? ------------------------------------------ MESSAGE PASSING EXAMPLE WITH SUPER define C2class = class baseobject, () () (initialize = method() noop; m1 = method () $m2(self); m2 = method () 3; m3 = method () 14 ) 0; define D2class = class C2class, () () (m2 = method () $m3(super); m3 = method () 5 ) 0; %%% FOR YOU TO DO %%% --> $m1(simpleinstance C2class); --> $m1(simpleinstance D2class); ------------------------------------------ What is the result (if any) of $m1(simpleinstance C2class) ? What is the result (if any) of $m1(simpleinstance D2class) ? D. scope issues ------------------------------------------ LEXICAL SCOPE vs. INSTANCE VARIABLES ;;; Figure 7.2.5 : page 230 define aclass = class baseobject, (cv) (iv) () &&cv := 7; let x = 3; cv = 4; iv = 5 in let bclass = class aclass, () () (initialize = method () &iv := +(x, &&cv); getiv = method () &iv ) 0 in let b = simpleinstance bclass in list($getiv(b), x, cv, iv); ------------------------------------------ What does this return? How would you explain the scoping? ------------------------------------------ fig 7.2.6 STATIC vs. DYNAMIC INHERITANCE OF INSTANCE VARIABLES define aclass = class baseobject, (cv) (iv) (initialize = method () &iv := 8; getcv = method () &&cv; getiv = method () &iv) &&cv := 6; define bclass = class aclass, (cv) (iv) (initialize = method () begin $initialize(super); &iv := 9 end) &&cv := 7; define x = simpleinstance bclass; define c = $getcv(x); define i = $getiv(x); ------------------------------------------ What is the value of c? i? what could they be? ------------------------------------------ TERMS static = references to class and instance vars resolved in environment of the dynamic = references resolved in environment of the ------------------------------------------ What does our interpreter do? How can you tell? III. Meta-Classes (EOPL 7.3) A. what is a meta-level? ------------------------------------------ GOING META (7.3) arguments vs. arguments about how to argue logic vs. meta-logic worries vs. worrying about worrying forms vs. the forms of forms (Plato) types vs. types of types voting vs. voting about how to vote law vs. laws about laws (constitutions) books vs. books about books ------------------------------------------ What's a meta-question? So what's a meta-class? What's a meta-meta-class? Is a meta-class a class? B. meta-classes 1. motivation ------------------------------------------ WHY HAVE META-CLASSES? ------------------------------------------ Where would a method to create a subclass go? 2. terms ------------------------------------------ EQUIVALENCES class variable = instance variable of class method = method of ------------------------------------------ 3. plan ------------------------------------------ ELIMINATING THE DISTINCTION BETWEEN CLASSES AND INSTANCES or ALLOWING FOR AN INFINITE NUMBER OF LEVELS or MAYBE PLATO WASN'T WRONG HE JUST WORKED BOTTOM UP step 1: only have instances step 2: instances can play both roles step 3: instances store role purpose ______________________________________ class parent var names meth env vector cells ------------------------------------------ How is the parent used in the interpreter? C. implementation 1. syntax ------------------------------------------ CHANGES TO DEFINED LANGUAGE Replacement syntax for class expression: ::= instance , , Abstract syntax: (define-record new-instance ------------------------------------------ What happened to the class variables? What happended to the initialization exp? 2. semantics ------------------------------------------ CONCEPTUAL DOMAINS Domains: Method-Environment = -> Method Environment = -> Denoted-Value Denoted-Value = Cell(Expressed-Value) Expressed-Value = Number + Procedure + List(Expressed-Value) + Void + Instance + Open-Method Procedure = prim-proc + closure Instance = Class = Open-Method = Class-Thunk -> Method Class-Thunk = () -> Class Method = {Expressed-Value}* -> Expressed-Value Data structures: (define-record instance Convenience procedures: (define class->m-env instance->m-env) (define class->i-vars instance->i-vars) (define class->parent instance->parent) ------------------------------------------ Should we put the environment for the instance variables back together? What should have to change in the interpreter? ------------------------------------------ EVAL-EXP FOR SECTION 7.3 Like the 7.2 interpreter, but change: - split environment for class vars from (class->c-vars (something->value class)) (class->c-vals (something->value class)) to - use make-instance instead of make-class and give it the parent too ------------------------------------------ ------------------------------------------ HOW TO GET IT ALL STARTED? (define base-env ;; TYPE: Environment init-env) ; init-env of Chapter 5 ;;; Modified from Figure 7.3.1 (set! init-env (extend-env '(baseobject parentof classof) (map expressed->denoted (list (make-instance (make-nothing) (make-nothing) '() init-meth-env '#()) (procedure->expressed (make-prim-proc 'class->parent)) (procedure->expressed (make-prim-proc 'instance->class)))) base-env)) ------------------------------------------ How does it work that the symbols class->parent and instance->class are used? D. example ------------------------------------------ ;;; Figure 7.3.2 : page 236 define metametacountclass = instance baseobject, baseobject, (classcount) (initialize = method () &classcount := 0); define metacountclass = instance metametacountclass, baseobject, (instcount) (initialize = method () begin &instcount := 0; &&classcount := +(&&classcount, 1) end; new = method () instance self, baseobject, () (); howmany = method () &&classcount); ------------------------------------------ ------------------------------------------ ;;; Figure 7.3.2 continued define countclass = instance metacountclass, baseobject, () (initialize = method () &&instcount := +(&&instcount, 1); howmany = method () &&instcount); define metastackclass = instance classof(metacountclass), metacountclass, (pushed) (initialize = method () begin &pushed := 0; $initialize(super) end); ------------------------------------------ ------------------------------------------ ;;; Figure 7.3.2 continued define stackclass = instance metastackclass, countclass, (stk, localpushed) (initialize = method () begin &localpushed := 0; &stk := emptylist; $initialize(super) end; ...); define boundedstackclass = instance classof(stackclass), stackclass, (bound) (initialize = method () begin &bound := 10; $initialize(super) end; ...); define stackinstance = $new(stackclass); define boundedstackinstance = $new(boundedstackclass); ------------------------------------------