14 decembrie 2014

Design of OO language

Ultima prezentare din #Principles of Programming Languages .
Design & implementare.

Ca design, limbajul suporta crearea obiectelor cu campuri si metode, accesarea lor din afara , precum si mostenire de clase. Mai multe in slide-urile de mai jos.


Implementare: aici (cod, teste, Readme)
-----

In acelasi timp, mi-am adus aminte de un proiect la #Limbaje formale si automate, care presupune parsarea si validarea unui limbaj de programare (aici), folosind Flex. Limbajul are propria sintaxa care se bazeaza pe folosirea tab-urilor. Programul de parsare se ocupa de gestiunea variabilelor, recunoasterea tipurilor de instructiune, etc.

09 decembrie 2014

Eopl3: chapter 9.4 solution to exercise 9.6

> lang.scm__________________________________________________________

        (expression
            ("instanceof" expression identifier)
        instance-exp)

> interp.scm________________________________________________________

        (instance-exp (expr className)
            (let ((hisClass (object->class-name (value-of expr env))))
                (if (eq? className hisClass) (bool-val #t) (bool-val #f))))

_______________________Test:______________________________________ __

class c1 extends object
    field x
    field y
    method initialize ()
        begin
         set x = 11;
         set y = 12
        end
    method m1 ()
        -(x,1)

class c2 extends object
    field x
    method initialize ()
        begin
         set x = 0
        end

let o2 = new c2() in instanceof o2 c1    ;; #f

;; let o2 = new c1() in instanceof o2 c1    ;; #t


alte ex rezolvate de altii: aici

Eopl3: chapter 9.4 solution to exercise 9.16

Adding overloading of methods.
Idea: each method name is stored as methodName*nrParam (thus there can be many possible methods with the same name but different number of parameters.

> classes.scm______________________________________________________

;; when saving a method, *nrParam is appended to method-name

  (define method-decls->method-env
    (lambda (m-decls super-name field-names)
      (map
        (lambda (m-decl) ;; ex 9.16
          (cases method-decl m-decl
            (a-method-decl (method-name vars body)
                ;; append *nrParam to the method-name
                (let ((newMethodName (string-append (symbol->string method-name) "*" (number->string (length vars)))))
                  (list (string->symbol newMethodName)
                    (a-method vars body super-name field-names))))))
        m-decls)))


> interp.scm _______________________________________________________

;; initialize will called as initialize*0 or otherwise, depending on how the object is instantiated from class

        (new-object-exp (class-name rands)
          (let ((args (values-of-exps rands env))
                (obj (new-object class-name)))
            (apply-method
    (find-method class-name (string->symbol (string-append (symbol->string 'initialize) "*" (number->string (length rands)))))
              obj
              args)
            obj))

;; regular method call also will point to the method with the nr of parameters used for call

        (method-call-exp (obj-exp method-name rands)
          (let ((args (values-of-exps rands env))
                (obj (value-of obj-exp env))
                (nrParam (length rands)))
            (apply-method
              (find-method (object->class-name obj)
                (string->symbol(string-append (symbol->string method-name) "*" (number->string nrParam))))
              obj
              args)))

Example of test:___________________________________________________

class c1 extends object
    field x
    field y
    method initialize () % before it would save only this init, ignoring the 2nd one, result was 10
        begin
         set x = 11;
         set y = 12
        end
    method initialize (param)
        begin
         set x = param;
         set y = 12
        end
    method m1 ()
        -(x,1)
    method m1 (param)
        -(x,param)

let o2 = new c1(7) in send o2 m1(4)        % 3, overloading

Eopl3: chapter 9.4 solution to exercise 9.13

Adding final methods (which cannot be overridden).
--------------------------------------------
> lang.scm_____________________________________________________________

        (method-decl
            ("final" "method" identifier
                  "("  (separated-list identifier ",") ")" ; method formals
              expression)
        a-method-decl-final)

;; So we created a new type of method-decl, called a-method-decl-final

> classes.scm___________________________________________________________

;; First we add a new field for the a-method data structure

  (define-datatype method method?
    (a-method
      (vars (list-of symbol?))
      (body expression?)
      (super-name symbol?)
      (field-names (list-of symbol?))
      (isFinal boolean?)
    ))

;; We check for method-decl in 2 cases (regular one + the one added above).
;; In the first case, in case the super-class is not object, we check if the method already existed
;; If yes, we check its status: final or not. If final, don't override, else override;
;; when we override, we set the final field to #f
;; In the 2nd case, same steps basically, but when we override, we set the final field to #t (final)

  (define method-decls->method-env
    (lambda (m-decls super-name field-names)
      (map
        (lambda (m-decl)
          (cases method-decl m-decl
            (a-method-decl (method-name vars body)        ;; create a non-final method
                (if (eq? super-name 'object) (list method-name (a-method vars body super-name field-names #f))
                ;; else check if it didnt exist before in the super class, as a final
                (let ((possibleMethod (find-method super-name method-name)))
                    (if (eq? possibleMethod #f)
                        (list method-name (a-method vars body super-name field-names #f))    ;;  not found before, create the method
                        ;; found before so check if it's final
                        (cases method possibleMethod (a-method (vars body super fnames isFinal)   
                            (if (eq? isFinal #t)
                                (list 'xxx (a-method vars body super-name field-names #f))    ;; make a dummy, don't overwrite
                                (list method-name (a-method vars body super-name field-names #f))    ;; else overwrite
                            )))
                ))))
            (a-method-decl-final (method-name vars body)                ;; final method
                (if (eq? super-name 'object) (list method-name (a-method vars body super-name field-names #t))
                ;; else check if it didnt exist before in the super class, as a final
                (let ((possibleMethod (find-method super-name method-name)))
                    (if (eq? possibleMethod #f)
                        (list method-name (a-method vars body super-name field-names #t))    ;;  not found before, create the method
                        ;; found before so check if it's final
                        (cases method possibleMethod (a-method (vars body super fnames isFinal)   
                            (if (eq? isFinal #t)
                                (list 'xxx (a-method vars body super-name field-names #t))    ;; make a dummy, don't overwrite
                                (list method-name (a-method vars body super-name field-names #t))    ;; else overwrite
                            )))
                )))
        )))
        m-decls)))

;; a small change in find-method

  (define find-method
    (lambda (c-name name)
      (let ((m-env (class->method-env (lookup-class c-name))))
        (let ((maybe-pair (assq name m-env)))
          (if (pair? maybe-pair) (cadr maybe-pair)
            (begin
                (report-method-not-found name) #f)
    ;; ex. 9.13
    )))))


> interp.scm____________________________________________________________

;; a small change to accommodate the new field isFinal

  (define apply-method                   
    (lambda (m self args)
      (cases method m
        (a-method (vars body super-name field-names isFinal) ;; ex 9.13
          (value-of body
            (extend-env vars (map newref args)
              (extend-env-with-self-and-super
                self super-name
                (extend-env field-names (object->fields self)
                  (empty-env)))))))))


__________           _     Test... exemplu_____                ________________

class c1 extends object
    field x
    field y
    method initialize ()
        begin
         set x = 11;
         set y = 12
        end
    final method m1 (a)
        -(x,a)

class c2 extends c1
    method initialize ()
        begin
         super initialize()
        end
    method m1 (a)
        -(a,1)

let o2 = new c2() in send o2 m1(55)        % m1 cannot be overwritten, should write -44

Cursuri noi online care mi-au atras atentia