~ubuntu-branches/ubuntu/trusty/librep/trusty

« back to all changes in this revision

Viewing changes to lisp/rep/data/objects.jl

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2001-11-13 15:06:22 UTC
  • Revision ID: james.westby@ubuntu.com-20011113150622-vgmgmk6srj3kldr3
Tags: upstream-0.15.2
ImportĀ upstreamĀ versionĀ 0.15.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#| objects.jl -- very basic OO system
 
2
 
 
3
   $Id: objects.jl,v 1.6 2001/08/01 03:14:46 jsh Exp $
 
4
 
 
5
   Copyright (C) 2000 John Harper <john@dcs.warwick.ac.uk>
 
6
 
 
7
   This file is part of librep.
 
8
 
 
9
   librep is free software; you can redistribute it and/or modify it
 
10
   under the terms of the GNU General Public License as published by
 
11
   the Free Software Foundation; either version 2, or (at your option)
 
12
   any later version.
 
13
 
 
14
   librep is distributed in the hope that it will be useful, but
 
15
   WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
   GNU General Public License for more details.
 
18
 
 
19
   You should have received a copy of the GNU General Public License
 
20
   along with Jade; see the file COPYING.  If not, write to
 
21
   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
22
|#
 
23
 
 
24
(define-structure rep.data.objects
 
25
 
 
26
    (export object
 
27
            objectp)
 
28
 
 
29
    (open rep)
 
30
 
 
31
  ;; Commentary:
 
32
 
 
33
  ;; This module provides an extremely simple message-passing object
 
34
  ;; implementation, with support for single inheritance. The `object'
 
35
  ;; form expands to a lambda expression, hence it captures local
 
36
  ;; bindings for the method implementations.
 
37
 
 
38
  ;; Syntax is:
 
39
 
 
40
  ;;    (object BASE-OBJECT METHOD...)
 
41
 
 
42
  ;; each METHOD is either ((METHOD-NAME . PARAM-LIST) BODY...), or
 
43
  ;; (METHOD-NAME FUNCTION).
 
44
 
 
45
  ;; PARAM-LIST currently isn't the full lambda spec, just a list of
 
46
  ;; symbols. The list can be dotted to a symbol to make a #!rest
 
47
  ;; parameter. All parameters are optional (i.e. default to nil)
 
48
 
 
49
  ;; Any unknown methods are passed off to BASE-OBJECT, or if that is
 
50
  ;; nil, an `unknown-method' error is signalled.
 
51
 
 
52
  ;; Each object has the variable `self' bound to the closure
 
53
  ;; representing itself. (In superclasses, `self' points to the
 
54
  ;; subclass originally called into)
 
55
 
 
56
  ;; Example:
 
57
 
 
58
  ;; (define obj (object nil
 
59
  ;;               ((foo a b) (+ a b))
 
60
  ;;               (bar -)))
 
61
 
 
62
  ;; (obj 'foo 2 1) => 3
 
63
  ;; (obj 'bar 2 1) => 1
 
64
  ;; (obj 'baz 2 1) error--> unknown method: baz
 
65
 
 
66
  (define (make-let-bindings spec args-var)
 
67
    (let loop ((rest spec)
 
68
               (i 0)
 
69
               (out '()))
 
70
      (cond ((null rest) (nreverse out))
 
71
            ((atom rest)
 
72
             (loop '() (1+ i) (cons `(,rest (nthcdr ,i ,args-var)) out)))
 
73
            ((memq (car rest) '(#!optional #!rest #!key &optional &rest))
 
74
             (error "Lambda-list keywords aren't implemented for objects: %s" spec))
 
75
            (t (loop (cdr rest) (1+ i)
 
76
                     (cons `(,(car rest) (nth ,i ,args-var)) out))))))
 
77
 
 
78
  (defmacro object (base-object . methods)
 
79
    (let ((op (gensym))
 
80
          (args (gensym))
 
81
          (self (gensym))
 
82
          (base (gensym)))
 
83
      `(let ((,base ,base-object))
 
84
         (letrec ((,self
 
85
                  (lambda (,op #!key (self ,self) . ,args)
 
86
                    (case ,op
 
87
                      ,@(mapcar
 
88
                         (lambda (method)
 
89
                           (cond ((consp (car method))
 
90
                                  ;; ((METHOD-NAME . PARAM-LIST) BODY...)
 
91
                                  `((,(caar method))
 
92
                                    (let ,(make-let-bindings
 
93
                                           (cdar method) args)
 
94
                                      ,@(cdr method))))
 
95
                                 ((symbolp (car method))
 
96
                                  ;; (METHOD-NAME FUNCTION)
 
97
                                  `((,(car method))
 
98
                                    (apply ,(cadr method) ,args)))))
 
99
                         methods)
 
100
                      (t (if ,base
 
101
                             (apply ,base ,op #:self self ,args)
 
102
                           (signal 'unknown-method (list ,op))))))))
 
103
           ,self))))
 
104
 
 
105
  (define objectp closurep)
 
106
 
 
107
  (put 'unknown-method 'error-message "Unknown method call"))