CS 541 Lecture -*- Outline -*- * Structural operational semantics of mini Cecil work out the semantics of mini Cecil in class. ** overview *** multiple implementations of a type this allow variant-like (sum) data structures (otherwise only have record-like (product) structures) very simple kind of subtyping ------------------------------------------ MULTIPLE IMPLEMENTATIONS OF A TYPE type Point, implemented by class Cartesian instance vars: x y class Polar instance vars: rho theta methods abscissa(p@Cartesian:Point):Int abscissa(p@Polar:Point):Int rotate(p@Any:Point):Void upd_abscissa(p@Cartesian:Point, i@Any:Int):Void upd_abscissa(p@Polar:Point, i@Any:Int):Void upd_ordinate(p@Cartesian:Point, i@Any:Int):Void upd_ordinate(p@Polar:Point, i@Any:Int):Void equal(p@Cartesian:Point, p@Polar:Point):Bool ------------------------------------------ ------------------------------------------ MULTIPLE IMPLEMENTATIONS OF A TYPE 2 type IntList, implemented by class Nil no instance vars class Cons instance vars: car cdr methods null(l@Nil:IntList):Bool { ^true } null(l@Cons:IntList):Bool { ^false } hd(l@Cons:IntList):Int { ^l.car } tl(l@Cons:IntList):IntList { ^l.cdr } hd(l@Nil:IntList):Int { ^hd(l) } tl(l@Nil:IntList):IntList { ^tl(l) } length_helper(l@Any:IntList, res@Any:Int):Int { if null(l) then res := 0 else res := length(tl(l)); ^res } length(l@Any:IntList):Int { ^length_helper(l,0)} length(l@Nil:IntList):Int { ^0} ------------------------------------------ *** multi-methods ------------------------------------------ MULTI-METHODS and MESSAGE PASSING Metaphor: Smalltalk message send ___ --------- /__/| |\ what /| - |__|/ | ------- | -- | args | - |---------| Multi-method (Cecil) message send ((())) N=========================N (what ) E ___ ___ ___ E ( ) T=/__/|====/__/|====/__/|=T (--) |__|/ |__|/ |__|/ () o ------------------------------------------ ------------------------------------------ DIFFERENCES BETWEEN MULTI-METHODS AND SMALLTALK METHODS mutlimethods: - are not part of a class definition. - are called based on run-time classes of *all* arguments, not just first - have declaration that tells what classes of arguments they respond to, i.e., specialize on. - have access to instance vars of arguments that are specialized - raise software engineering concerns about modularity and encapsulation - generalize methods in Smalltalk. ------------------------------------------ for the last problem, see our paper on type checking and modules for Cecil. *** type checking considerations In type checking, only have type information, don't have class information. Want to be conservative, prevent the following kinds of errors before run-time. ------------------------------------------ PROBLEMS THAT MAY ARISE IF TYPES are not CLASSES 1. incomplete set of methods e.g., no hd, tl specialized on class Nil 2. inconsistent set of methods = possible that the set of applicable methods does not have a unique most specific element. e.g., equal(p@Cartesian:Point, p2@Any:Point):Bool equal(p@Any:Point, p2@Polar:Point):Bool consider send equal(new_Cartesian(...), new_Polar(...)) 3. incompatible class and type in method formal declaration e.g., equal(p@Cartesian:Int p2@Polar:Bool):Bool ------------------------------------------ *** class and method orderings the class ordering is simplified, in that no inheritance motivation is to be able to compare methods to determine when one is more specific than another ------------------------------------------ CLASS ORDERINGS specializer ordering Nil <= Any Cons <= Any Nil <= Nil in general, C1 <= C2 iff ___________________ ------------------------------------------ C1 = C2 or C2 = Any ------------------------------------------ specializer sequence ordering [Nil] <= [Any] [Nil, Nil] <= [Nil,Any] <= [__,__] in general, [C1,...,Cn] <= [C1',...,Cn'] iff _____________________________ ------------------------------------------ for all i, Ci <= Ci' ------------------------------------------ USE OF ORDERING IN MESSAGE SEND At *runtime* - each object has a class to execute: send msg(E1,...,En); 1. evaluate [E1, ..., En] get objects [o1, ... ,on] 2. find classes of [o1, ... ,on] get class list [C1, ... ,Cn] 3. Let applicable-methods(msg, [C1,...,Cn]) = { m | m is a method with name msg, and [C1,...,Cn] <= specializers(m)} 4. The set of applicable methods, found in step 3, must have a unique, most specific element, that is the method to call 5. call that method. ------------------------------------------ ** operational semantics coded in \Prolog ------------------------------------------ OVERVIEW OF MINI-CECIL SEMANTIC MODULES mini_cecil_abstract_syntax ^ | algebra store ^ ^ | | visibles env algebra_with_store ^ ^ ^ | | | mini_cecil_with_env_and_store ------------------------------------------ algebra gives form of algebras, visibles gives a particular algebra for the built-in types. ** algebras splitting semantics into 2 parts: 1. exprs and statements compute on top of algebra 2. model of classes and methods called an algebra *** why? modularity of semantics ability to look at properties of one part without going into the other. study representation independence *** what is an algebra? def: an algebra is a mathematical model of classes and methods has two parts 1. signature = syntactic interface set of types {Int, Bool} information about messages (resType "and" (Bool,Bool)) = Bool (resType "or" (Bool,Bool)) = Bool .... (resType "add" (Int,Int)) = Int 2. semantics carrier set (universe, domain) for each type Bool = {tt,ff} Int = {0, -1, 1, -2, 2, ...} interpretation of messages A add (3,4) = 7 etc. ** without environments perhaps should create this on the fly instead of showing it. ------------------------------------------ EVALUATION SEMANTICS OF MINI CECIL (WITHOUT ENVIRONMENTS) module mini_cecil. import maps mini_cecil_abstract_syntax algebra visibles debug_write. %%%% the evalsto relation for expressions type evalsto expression -> value -> o. (evalsto (intLiteral N) (inInteger N)). (evalsto true (inTruthValue tt)). (evalsto false (inTruthValue ff)). ((mappred evalsto Exprs Vs), (evaluate_in_algebra algebraVIS MsgName Vs Ans)) => %----------------------------------- (evalsto (msgExpr MsgName Exprs) Ans). ------------------------------------------ Q: why don't the others work? ** environments will assume that variable names denote values in env (this will turn out to be wrong...) when we come to procCallExpr, have to make the environment denote either values or procedure closures hence the bindable domain. see the files mini_cecil_with_env.mod test_mini_cecil_with_env.mod in this directory. Q: can we do statements with this? not the assignment statement. ** stores needed to handle variables correctly (don't want to update the environment when eval exprs and statements). see the files store.mod mini_cecil_with_env_and_store.mod test_mini_cecil_with_env_and_store.mod in this directory work out clauses for expressions and the statements that don't have to do with objects. Q: can you do the if and seqStmt clauses? pass out the files. look in detail at store: empty_store, alloc, update, access. - draw picture of store ** procedure definitions need to make up procedure closures and put them in the environment. see the file mini_cecil_with_env_and_store.mod test_mini_cecil_with_env_and_store.mod -look at clauses for elaborate, run-main Q: are these recursive? Is there a way to make them recursive? Q: Looking at the semantics can you tell what a procedure means? Q: How does elaborateProcedure compare to elaborate? ** class and method definitions as a first step, need to change all clauses to pass an algebra. when compile a class named foo, compile methods: new_foo set_fn -- for each instance var named fn get_fn -- for each instance var named fn the get_ and set_ methods are generic, provided in algebra_with_store.mod the new_ method is a hack... Q: how to represent methods? as a closure? Is the environment needed? see the files mini_cecil_semantics.mod test_mini_cecil_semantics.mod algebra_with_store.mod in this directory Q: are methods recursive? mutually recursive? Q: what good has the split into algebra and rest of semantics done?