137 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Scheme
		
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Scheme
		
	
	
	
| 
 | ||
| 
 | ||
| 
 | ||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | ||
| ;;;                                                                 ;;;
 | ||
| ;;;                     S c o o p s                                 ;;;
 | ||
| ;;;                                                                 ;;;
 | ||
| ;;;      (c) Copyright 1985 Texas Instruments Incorporated          ;;;
 | ||
| ;;;                  All Rights Reserved                            ;;;
 | ||
| ;;;                                                                 ;;;
 | ||
| ;;;               File updated : 8/29/85                            ;;;
 | ||
| ;;;                                                                 ;;;
 | ||
| ;;;                   File : methods.scm                            ;;;
 | ||
| ;;;                                                                 ;;;
 | ||
| ;;;                 Amitabh Srivastava                              ;;;
 | ||
| ;;;                                                                 ;;;
 | ||
| ;;;    This file contains the adding of methods to classes          ;;;
 | ||
| ;;;                                                                 ;;;
 | ||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | ||
| 
 | ||
| 
 | ||
| ;;; is class1 before class2 in class ?
 | ||
| ;;; class1  is not equal to class2
 | ||
| 
 | ||
| 
 | ||
| (define %before
 | ||
|   (lambda (class1 class2 class)
 | ||
|     (or (eq? class1 class)
 | ||
|         (memq class2 (memq class1 (%sc-mixins (%sc-name->class class)))))))
 | ||
| 
 | ||
| ;;;
 | ||
| 
 | ||
| (macro define-method
 | ||
|   (lambda (e)
 | ||
|     (let ((class-name (caadr e))
 | ||
|           (method-name (cadr (cadr e)))
 | ||
|           (formal-list (caddr e))
 | ||
|           (body (cdddr e)))
 | ||
|        (list '%sc-class-add-method
 | ||
|              (list 'quote class-name)
 | ||
|              (list 'quote method-name)
 | ||
|              (list 'quote class-name)
 | ||
|              (list 'quote class-name)
 | ||
|              (%sc-expand
 | ||
|                  (cons 'lambda (cons formal-list body)))
 | ||
|             (list 'lambda '(env val)
 | ||
|                   (list 'set! (list 'access method-name 'env) 'val))))))
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ;;;
 | ||
| 
 | ||
| (define %sc-class-add-method
 | ||
|   (lambda (class-name method-name method-class mixin-class method assigner)
 | ||
|     (let ((class (%sc-name->class class-name)))
 | ||
|          (apply-if (assq method-name (%sc-method-values class))
 | ||
|             (lambda (entry)
 | ||
|               (set-cdr! entry method))
 | ||
|             (%sc-set-method-values class
 | ||
|                (cons (cons method-name method) (%sc-method-values class)))))
 | ||
|     (%compiled-add-method class-name method-name method-class mixin-class
 | ||
|                          method assigner)))
 | ||
| 
 | ||
| 
 | ||
| ;;;
 | ||
| 
 | ||
| (define %inform-subclasses
 | ||
|   (lambda (class-name method-name method-class mixin-class method assigner)
 | ||
|     ((rec loop
 | ||
|        (lambda (class-name method-name method-class mixin-class
 | ||
|                                        method assigner subclass)
 | ||
|          (if subclass
 | ||
|              (begin
 | ||
|                 (%compiled-add-method
 | ||
|                   (car subclass) method-name method-class class-name
 | ||
|                   method assigner)
 | ||
|                 (loop class-name method-name method-class mixin-class
 | ||
|                       method assigner
 | ||
|                       (cdr subclass))))))
 | ||
|      class-name method-name method-class mixin-class method assigner
 | ||
|      (%sc-subclasses (%sc-name->class class-name)))))
 | ||
| 
 | ||
| 
 | ||
| ;;;
 | ||
| 
 | ||
| (define %compiled-add-method
 | ||
|   (lambda (class-name method-name method-class mixin-class method assigner)
 | ||
|     (letrec
 | ||
|       ((class (%sc-name->class class-name))
 | ||
| 
 | ||
|        (insert-entry
 | ||
|          (lambda (previous current)
 | ||
|            (cond ((null? current)
 | ||
|                   (set-cdr! previous
 | ||
|                      (cons (cons method-class mixin-class) '())))
 | ||
|                  ((eq? mixin-class (cdar current))
 | ||
|                   (set-car! (car current) method-class))
 | ||
|                  ((%before mixin-class (cdar current)
 | ||
|                            class-name)
 | ||
|                   (set-cdr! previous
 | ||
|                      (cons (cons method-class mixin-class) current)))
 | ||
|                  (else '()))))
 | ||
| 
 | ||
| 
 | ||
|        (loop-insert
 | ||
|          (lambda (previous current)
 | ||
|            (if (not (insert-entry previous current))
 | ||
|                (loop-insert (current) (cdr current)))))
 | ||
| 
 | ||
|        (insert
 | ||
|          (lambda (entry)
 | ||
|            (if (insert-entry entry (cdr entry))  ;;; insert at head
 | ||
|                (add-to-environment)
 | ||
|                (loop-insert (cdr entry) (cddr entry)))))
 | ||
| 
 | ||
|        (add-to-environment
 | ||
|          (lambda ()
 | ||
|            (if (%sc-class-compiled class)
 | ||
|                (assigner (%sc-method-env class) method))
 | ||
|            (if (%sc-subclasses class)
 | ||
|                (%inform-subclasses class-name method-name method-class
 | ||
|                                   mixin-class method assigner))))
 | ||
| 
 | ||
|        (add-entry
 | ||
|          (lambda ()
 | ||
|            (%sc-set-method-structure class
 | ||
|              (cons (list method-name (cons method-class mixin-class))
 | ||
|                    (%sc-method-structure class)))
 | ||
|            (add-to-environment)))
 | ||
|       )
 | ||
| 
 | ||
|       (let ((method-entry (assq method-name (%sc-method-structure class))))
 | ||
|         (if method-entry
 | ||
|             (insert method-entry)
 | ||
|             (add-entry))
 | ||
|         method-name))))
 |