Com S 342 meeting -*- Outline -*- * Meta-Classes (EOPL 7.3) ** 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 ------------------------------------------ this is a common trait of computer scientists it's not the same as recursion within a level, but recursion between levels of description Q: What's a meta-question? something like this (:->) Q: So what's a meta-class? def: a *meta-class* is the class of a class Q: What's a meta-meta-class? Q: Is a meta-class a class? ** meta-classes *** motivation ------------------------------------------ WHY HAVE META-CLASSES? ------------------------------------------ - to do something when we create a class - reflection: giving the program access to information about itself at run-time - to make the language more OO, and hence more flexible, so can send messages to classes - to make the language more uniform and regular class objects are objects Q: Where would a method to create a subclass go? not in the class, that would be sent to an instance, should be in the class of a class, i.e., a metaclass This is also a feature of Smalltalk-80, Java also has some reflective features, but not this *** terms ------------------------------------------ EQUIVALENCES class variable = instance variable of class method = method of ------------------------------------------ ... meta-class ... meta-class *** 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 ------------------------------------------ ... take out class expression from syntax ... class role is to describe instances, instance role is to store data ... role purpose ______________________________________ class instance stores common info (var names, methods, ...) parent class inheritance var names class of instances' vars meth env class for instances vector cells instance for self Q: How is the parent used in the interpreter? ** implementation *** syntax ------------------------------------------ CHANGES TO DEFINED LANGUAGE Replacement syntax for class expression: ::= instance , , Abstract syntax: (define-record new-instance ------------------------------------------ Q: What happened to the class variables? not needed, as are instance variables of metaclasses Q: What happended to the initialization exp? not needed, as the initialize method of the metaclass does that. ... (class-exp parent-exp i-vars methdecls) *** 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) ------------------------------------------ ... Instance = Maybe(Class) x Maybe(Class) x {}* x Method-Environment x Vector(Denoted-Value) Class = Instance -- we went meta! ... (define-record instance (class parent i-vars m-env i-vals)) Q: Should we put the environment for the instance variables back together? No! Each half is for a different role. Q: What should have to change in the interpreter? just stuff relating to the class role; instance stuff is the same as always ------------------------------------------ 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 ------------------------------------------ ... (class->i-vars (something->value (instance->class (something->value class)))) (instance->i-vals (something->value class)) ; CORRECTED! note that using (instance->class (something->value inst)) would get dynamically scoped class variables, the book is wrong. ------------------------------------------ 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)) ------------------------------------------ Q: How does it work that the symbols class->parent and instance->class are used? interpretation happens in apply-prim-op, of course! ** 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); ------------------------------------------ Draw picture like 7.3.3 to illustrate this.