1 / 19

Objects and types

Objects and types. Typed languages = define a set of types in the language and assign a type to each expression in the program Type checking = how can we implement a simple type checker for a static typing language Do type checking in an OO language

zinnia
Download Presentation

Objects and types

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Objects and types • Typed languages = define a set of types in the language and assign a type to each expression in the program • Type checking = how can we implement a simple type checker for a static typing language • Do type checking in an OO language • State design decisions for implementing a Type Checker (TC)

  2. Design principles for our TC 1. Type checking for any language, not only OOL • Define a set of types for the language and define what means for a value v to be of type t. • If an expression e is assigned type t, then whenever e is executed, its value will be of type t. • No program that passes the checker will ever attempt to apply a non-procedure to an argument • No program that passes the checker will ever attempt to apply a procedure or primitive to the wrong number of arguments or to an argument of the wrong type

  3. Design principles for our TC 2. Type checking for an OOL • Fields in classes and methods are specified with their types, similar with what we shall do for the “any language” TC • The concepts of abstract classes and abstract methods are introduced • The concept of casting is introduced and the instanceof test • The concept of subtype polymorphism is added to the language • No program that passes the TC will ever send a message to an object for which there is no corresponding concrete method • No program that passes the TC will ever send a message to an object with the wrong number of arguments or with arguments of the wrong type

  4. 1. Type checking for a restricted (ordinary) language 1.1 Type specification in our language • A method to assign types to expressions and checking that no expression can possibly cause an operation to be performed on inappropriate arguments. • The TC either produces a type for the program or reject it and reports an error. • Types in the language • <type-exp> ::= int • int-type-exp ( ) • <type-exp> ::= bool • bool-type-exp ( ) • <type-exp> ::= ({<type-exp>}*(*) - > <type-exp>) • proc-type-exp (arg-texp result-texp) • Examples • (int * int - > int) type of + • (int - > (int - > int )) type of (lambda (x) (lambda (y) (+ x y))) • The language will be strongly statically typed.

  5. A type error in the language is defined as one of the following: • An attempt to apply an integer or a boolean to an argument • An attempt to apply a procedure or primitive to the wrong number of arguments • An attempt to apply a primitive expecting an integer to a non-integer • An attempt to use a non-boolean as the test in a conditional expression • The TC will mainly consist of a procedure: type-of-expression, based on the following idea: it will have the same structure as eval-expression but, instead of evaluating each expression in an environment containing the values of variables (env), it will process each expression in a type environment (tenv) containing the types of the variables. • type-expression has thus the following goal: when given an expression exp and a type environment tenv mapping eac variable to a type, it assigns to exp a type t with the property that: • whenever exp is executed in an environment in which each variable has the type specified in tenv, the resulting value has the type t. • Premisis: if we know the type of the value of each of the variables in an expression, we can deduce the type of the value of the expression. This type will be the type of the expression 5

  6. We shall consider the following features in the language: numbers, variables, if expressions, procedure expressions, primitive application, operator application, let expressions and associate the previously mentioned types. • In order to determine the resulting type of these expressions we will use Typing Rules = a standard way to specifying the typing behaviour of a language. Behavior of type-of-expression • Number (type-of-expression <n> tenv) = int • Variable (type-of-expression <id> tenv) = (apply-env tenv id) • Conditional specification (type-of-expression <test-exp> tenv) = bool (type-of-expression <true-exp> tenv) = t (type-of-expression <false-exp> tenv) = t (type-of-expression < if test-exp then true-exp else false-expp> tenv) = t 6

  7. Primitive application (rator rand1 …. randn) (t1 * t2 * … * tn) -> t if (type-of-expression <rator> tenv) = (t1 * t2 * … * tn) -> t and (type-of-expression <rand1> tenv) = t1 ……. and (type-of-expression <randn> tenv) = tn then (type-of-expression <(rator rand1 … randn)> tenv) = t • Procedure expression proc (x1, x2, …, xn) exp (t1 * t2 * … * tn) -> t ? (type-of-expression <exp> [x1=t1, …, xn=tn] tenv) = t (type-of-expression <proc (x1, x2, …, xn) exp> tenv) = (t1 * t2 * … * tn) -> t • Let expression if (type-of-expression <e1> tenv) = t1 and (type-of-expression <e2> tenv) = t2 … and (type-of-expression <en> tenv) = tn and (type-of-expression <body> [x1=t1, …, xn=tn] tenv) = t then (type-of-expression <let x1=e1 … xn=en in body> tenv) = t 7

  8. Problem: if we are trying to compute the type of a procedure expression, how are we going to find the types t1, …, tn of the bound variables? Two solutions: • Type checking: the programer must supply the missing information about the types of bound variables and the TC deduces the types of the other expressions and checks them for consistency • Type inference: the TC attempts to infer the types of the bound variables based on how variables are used in the program. 1.2 Type checking We require the programmer to include the types of all bound variables A procedure expression will look like: proc (t1 x1, t2 x2, …., tn xn) exp <expression> ::= proc ({<type-exp> <identifier>}* (,)) <expression> <expression> ::= true | false

  9. (define type-of-expression (lambda (exp tenv) (cases expression exp (lit-exp (number) int-type) (true-exp () bool-type) (false-exp () bool-type) (var-exp (id) (apply-tenv tenv id)) (if-exp (test-exp true-exp false-exp) (let ((test-type (type-of-expression test-exp tenv)) (false-type (type-of-expression false-exp tenv)) (true-type (type-of-expression true-exp tenv))) (check-equal-type! test-type bool-type test-exp) ;^ these tests either succeed or raise an error (check-equal-type! true-type false-type exp) true-type)) ----- see next slide -------- (Figure 4.5 EPL) 9 (define-datatypetype type? (atomic-type (name symbol?)) (proc-type (arg-types (list-of type?)) (result-type type?))) (define expand-type-expression (lambda (texp) (cases type-exp texp (int-type-exp () int-type) (bool-type-exp () bool-type) (proc-type-exp (arg-texps result-texp) (proc-type (expand-type-expressions arg-texps) (expand-type-expression result-texp)))))) (define expand-type-expressions (lambda (texps) (map expand-type-expression texps))) (Figure 4.3 EPL)

  10. type-of-proc-exp • It first converts t1, .., tn into a list of types • It then checks the bod y of the procedure • in the type environment and • binds the resulting type to result-type • last, it constructs a procedure type, • corresponding to (t1 * t2 * … * tn) -> t • following the specifications of the typing rules. • type-of-application • It first checks to see if the type of the operator • is a procedure type • It then checks to see if the number of arguments • expected by the procedure matches the no. • of arguments supplied • Then, for each assignment, it checks if the type • of the argument is equal to the type of the • corresponding operand • Then, if everything is OK, the type of the • application is the result type of the procedure • type-of-primitive • takes a primitive and returns its type • 10 (define type-of-expression (lambda (exp tenv) (cases expression exp ……… continued (proc-exp (texps ids body) (type-of-proc-exp texps ids body tenv)) (primapp-exp (prim rands) (type-of-application (type-of-primitive prim) (types-of-expressions rands tenv) prim rands exp)) (app-exp (rator rands) (type-of-application (type-of-expression rator tenv) (types-of-expressions rands tenv) rator rands exp)) (let-exp (ids rands body) (type-of-let-exp ids rands body tenv)) )))

  11. 2. Type checking for an OOL 2.1 Type specification in a simple typed OOL New features of the language: • Add a void type as the type of a set operation • Add list types to return composite results • An identifier used as a type is associated with the class of the same name • Classes take an optional abstract specifier • Methods require their result type to be specified, along with the types of their arguments • Abstract class – a class which will not be instantiated. This restriction can be neforced by a run-time check whenever a new object is created. See difference concrete class • Abstract method – a placeholder for a method to be supplied by each subclass of a class. Not applied but verified in every concrete class.

  12. New features of the language - continued: • Instanceof : instanceof exp class – checks if the object obtained by evaluating exp is an instance of class or of one of its descendants. Returns true or false • Cast : cast exp class – checks if the object exp is an instance of class and returns the object or an error • Subtype polymorphism – objects in a certain class can be regarded as instances of any of the ancestors classes of that class. To cope with these modifications we need: • - modifications to method declaration processing • - modifications to the evaluation of expressions See Figure 6.2 EPL for concrete and abstract syntax of this language Modifications to method declaration Datatype method-decl a-method-decl result-texp, name, arg-type-exps, ids, method-body an-abstract-method-decl result-texp, name, arg-type-exps, ids 12

  13. abstract class tree extends object method int initialize ( ) 1 abstract method int sum ( ) abstract method bool equal (tree t) class interior_node extends tree field tree left field tree right method void initialize (tree l, tree r) begin set left = l; set right = r end method tree getleft ( ) left method tree getright ( ) right method int sum ( ) +(send left sum( ), send right sum ( )) method bool equal (tree t) if instanceof t interior-node then if send left equal (send cast t interior_node getleft ( )) then send right equal (send cast t interior_node getright ( )) else false else false class leaf_node extends tree field int value method void initialize (int v) set value = v method int sum ( ) value method int getvalue ( ) value method bool equal (tree t) if instanceof t leaf-node then zero? (- (value, send cast t leaf_node getvalue ( ))) else false let o1 = new interior_node (new interior_node (new leaf_node (3), new leaf_node (4)), new leaf_node (5)) in list (send o1 sum( ), if send o1 equal(o1) then 100 else 200) 13

  14. Modifications to apply-method (define apply-method (lambda (method host-name self args) (let ((ids (method->ids method)) (body (method->body method)) (super-name (method->super-name method)) (field-ids (method->field-ids method)) (fields (object->fields self))) (eval-expression body (extend-env (cons '%super (cons 'self ids)) (cons super-name (cons self args)) (extend-env-refs field-ids fields (empty-env))))))) 14

  15. Modifications to eval-expression (cast-exp (exp name) (let ((obj (eval-expression exp env))) (if (is-subclass? (object->class-name obj) name) obj (eopl:error 'eval-expression "Can't cast object to type ~s:~%~s")))) (instanceof-exp (exp name) (let ((obj (eval-expression exp env))) (if (is-subclass? (object->class-name obj) name) the-true-value the-false-value))) 15

  16. 2.2 The type checker Goal of the type checker = no program that passes the TC will ever: • Snd a essage to an object for which there is no corresponding method • Send a message to an object with the wrong number of arguments or with arguments of the wrong type • Attempt to create an object of an abstract class, or an object of a concrete class in which one of the required abstract methods of a superclass has not been supplied (comments on initialiaze) • The TC will mainly consist of a procedure: type-of-expression, based on the following idea: it will have the same structure as eval-expression but, instead of evaluating each expression in an environment containing the values of variables (env), it will process each expression in a type environment (tenv) containing the types of the variables.

  17. In an OO paradigm we have two competing notions: • Types • Classes • Can we consider the class of an object as • the type of that object? • Policy: we introduce a type c for each class c and say that • an object is a value of type c whenever its class is either c or • a class that is a subclass of c • (define-datatype type type? • (atomic-type • (name symbol?)) • (list-type • (value-type type?)) • (class-type • (name symbol?)) • (proc-type • (arg-types (list-of type?)) • (result-type type?))) 17

  18. (define type-of-program • (lambda (pgm) • (cases program pgm • (a-program (c-decls exp) • (statically-elaborate-class-decls! c-decls) • (type-of-expression exp (empty-tenv)))))) • statically-elaborate-class-decls! • Processes a class declaration and builds a static class environment. This environment will be used by type-of-expression • The static class enviroment is like an ordinary class environment + the types of the method fields, the types of the methods and its parents • A class contains all the fields and methods accessible from that class. For each method we construct a static method. • Statically-roll-up-method-decls and statically-merge-methods produce a list of static methods, taking inheritance into account. Methods are placed in order of declaration. If a method of an ancestor class is overriden, the newer method is installed in place of the ancestor method. Hence, in each class there is at most one method for each method name. • Exception: initialize • 18

  19. Then the static class information is added to the static class environment by add-to-static-class-env! Then each of the method declarations is checked using typechecked-method-decl! Which builds a type environment that matches the runtime environment built by apply-method. (define typecheck-method-decl! (lambda (m-decl self-name super-name field-ids field-types) (cases method-decl m-decl (a-method-decl (result-texp name id-texps ids body) (let ((id-types (expand-type-expressions id-texps))) (let ((tenv (extend-tenv (cons '%super (cons 'self ids)) (cons (class-type super-name) (cons (class-type self-name) id-types)) (extend-tenv field-ids field-types (empty-tenv))))) (let ((body-type (type-of-expression body tenv))) (check-is-subtype! body-type (expand-type-expression result-texp) m-decl))))) (an-abstract-method-decl (result-texp name id-texps ids) #t)))) 19

More Related