((not (listp fields)) (error "`fields` non è una lista"))
((not (listp methods)) (error "`methods` non è una lista"))
((or (null classname)
- (not (symbolp classname))) (error "`classname` non è un simbolo")))
+ (not (symbolp classname))) (error "'~A' non è un simbolo"
+ classname)))
;; Aggiunge la coppia `classname` e classe in forma di lista
;; all'hash-table
** Creazione della classe in formato lista
#+begin_src lisp :tangle ool.lisp
(defun make-class (parents fields methods)
+ (unless (null fields)
+ (unless (equal (car fields) 'fields)
+ (error "Il primo argomento della lista di fields ~S"
+ "deve essere il simbolo 'fields'")))
+ (unless (null methods)
+ (unless (equal (car methods) 'methods)
+ (error "Il primo argomento della lista di methods ~S"
+ "deve essere il simbolo 'methods'")))
+
+ (type-check-fields (cdr fields))
(inherit (list :type 'class
:parents parents
:fields (cdr fields)
;; Se il genitore di `super` corrente NON è un membro
;; della lista dei genitore del figlio
(if (not (member (car super-parents) child-parent))
- ;; fai una chiamata ricorsiva aggiungendolo ai genitori del figlio
- (merge-parents (cdr super-parents) (cons (car super-parents) child-parent))
+ ;; fai una chiamata ricorsiva
+ ;; aggiungendolo ai genitori del figlio
+ (merge-parents (cdr super-parents)
+ (cons (car super-parents) child-parent))
;; altrimenti vai al prossimo senza aggiungerlo
(merge-parents (cdr super-parents) child-parent))))
#+end_src
(defun merge-parts (parent-fields class-fields)
(if (null parent-fields)
class-fields
- (if (not (field-name-exists (first (car parent-fields)) class-fields))
- (merge-parts (cdr parent-fields) (cons (car parent-fields) class-fields))
+ (if (not (field-name-exists (first (car parent-fields))
+ class-fields))
+ (merge-parts (cdr parent-fields)
+ (cons (car parent-fields) class-fields))
(merge-parts (cdr parent-fields) class-fields))))
;; È necessaria questa funzione in quanto i field sono a loro volta
(class-spec name)
nil))
#+end_src
+
+** Controllo tipo valore
+#+begin_src lisp :tangle ool.lisp
+(defun type-check-fields (fields)
+ (cond ((null fields) nil)
+ (t (type-check-field (car fields))
+ (type-check-fields (cdr fields)))))
+
+
+(defun type-check-field (field)
+ (unless (listp field)
+ (error "~S ~S" "Un field di un classe o è una terna (name value type)"
+ "o una coppia (name value)"))
+ (cond ((= (length field) 2) t)
+ ((= (length field) 3) (type-check (second field) (third field)))
+ (t (error "Un field di un classe ~S ~S"
+ "o è una terna (name value type)"
+ "o una coppia (name value)"))))
+
+(defun type-check (value type)
+ (unless (typep value type) (error "~A non è di tipo ~A" value type)))
+#+end_src
((not (listp fields)) (error "`fields` non è una lista"))
((not (listp methods)) (error "`methods` non è una lista"))
((or (null classname)
- (not (symbolp classname))) (error "`classname` non è un simbolo")))
+ (not (symbolp classname))) (error "'~A' non è un simbolo"
+ classname)))
;; Aggiunge la coppia `classname` e classe in forma di lista
;; all'hash-table
(gethash name *classes-specs*))
(defun make-class (parents fields methods)
+ (unless (null fields)
+ (unless (equal (car fields) 'fields)
+ (error "Il primo argomento della lista di fields ~S"
+ "deve essere il simbolo 'fields'")))
+ (unless (null methods)
+ (unless (equal (car methods) 'methods)
+ (error "Il primo argomento della lista di methods ~S"
+ "deve essere il simbolo 'methods'")))
+
+ (type-check-fields (cdr fields))
(inherit (list :type 'class
:parents parents
:fields (cdr fields)
;; Se il genitore di `super` corrente NON è un membro
;; della lista dei genitore del figlio
(if (not (member (car super-parents) child-parent))
- ;; fai una chiamata ricorsiva aggiungendolo ai genitori del figlio
- (merge-parents (cdr super-parents) (cons (car super-parents) child-parent))
+ ;; fai una chiamata ricorsiva
+ ;; aggiungendolo ai genitori del figlio
+ (merge-parents (cdr super-parents)
+ (cons (car super-parents) child-parent))
;; altrimenti vai al prossimo senza aggiungerlo
(merge-parents (cdr super-parents) child-parent))))
(defun merge-parts (parent-fields class-fields)
(if (null parent-fields)
class-fields
- (if (not (field-name-exists (first (car parent-fields)) class-fields))
- (merge-parts (cdr parent-fields) (cons (car parent-fields) class-fields))
+ (if (not (field-name-exists (first (car parent-fields))
+ class-fields))
+ (merge-parts (cdr parent-fields)
+ (cons (car parent-fields) class-fields))
(merge-parts (cdr parent-fields) class-fields))))
;; È necessaria questa funzione in quanto i field sono a loro volta
(if (equal (getf (class-spec name) :type) 'class)
(class-spec name)
nil))
+
+(defun type-check-fields (fields)
+ (cond ((null fields) nil)
+ (t (type-check-field (car fields))
+ (type-check-fields (cdr fields)))))
+
+
+(defun type-check-field (field)
+ (unless (listp field)
+ (error "~S ~S" "Un field di un classe o è una terna (name value type)"
+ "o una coppia (name value)"))
+ (cond ((= (length field) 2) t)
+ ((= (length field) 3) (type-check (second field) (third field)))
+ (t (error "Un field di un classe ~S ~S"
+ "o è una terna (name value type)"
+ "o una coppia (name value)"))))
+
+(defun type-check (value type)
+ (unless (typep value type) (error "~A non è di tipo ~A" value type)))