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

01 decembrie 2014

ssh fara parola (config & debug)

Presupunem ca avem 2 calc, x1@hostx si y1@hosty.

Pt hostx: in ~/.ssh stergem continutul (daca exista) din fisierele authorized_keys & known_hosts, pentru a o lua de la capat. Daca x1 != y1, se face acelasi lucru si pt hosty.

Rulam pe hostx:
su - x1
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa

Se transfera fisierul id_dsa.pub pe hosty (daca x1 != y1) si se pune continutul in authorized_keys. Daca x1 == y1, atunci se executa pe oricare dintre hostx sau
hosty:
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys

Rulam pe hosty:
su -y1
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa_y1

Idem ca mai sus (transferul id_dsa_y1.pub pe hostx), si se executa pe hostx ceva asemanator cu:
cat ~/.ssh/id_dsa_y1.pub >> ~/.ssh/authorized_keys

!! id_dsa_y1 nu trebuie suprascris peste id_dsa, daca x1 == x2

Acum x1 se poate conecta la y1 fara parola, cu:
ssh y1@hosty
Si vice-versa.

Debug:
* verificare permisiuni pe x1 si y1:
- home directory, directorul .ssh si fisierul authorized_keys sa poata fi scrise (w) doar de owner; citite cel putin de owner (r);
- cheile private trebuie sa poate fi citite si scrise doar de owner, iar cheile publice trebuie sa poata sa fie citite si din exterior (non-owner)
- permisiunile se modifica cu: chmod [value] [fisier]

* daca tot nu merge fara parola, se pot activa mesajele in ssh (verbose) prin:
ssh -vv y1@hosty
Acestea explica mecanismul de conectare si ce anume nu a mers.