1 ;;; luna.el --- tiny OOP system kernel
3 ;; Copyright (C) 1999 Electrotechnical Laboratory, JAPAN.
5 ;; Author: MORIOKA Tomohiko <tomo@m17n.org>
8 ;; This file is part of FLIM (Faithful Library about Internet Message).
10 ;; This program is free software; you can redistribute it and/or
11 ;; modify it under the terms of the GNU General Public License as
12 ;; published by the Free Software Foundation; either version 2, or (at
13 ;; your option) any later version.
15 ;; This program is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ;; General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
27 (eval-when-compile (require 'cl))
29 (defmacro luna-find-class (name)
30 "Return the luna-class of the given NAME."
31 `(get ,name 'luna-class))
33 (defmacro luna-set-class (name class)
34 `(put ,name 'luna-class ,class))
36 (defmacro luna-class-obarray (class)
39 (defmacro luna-class-parents (class)
42 (defmacro luna-class-number-of-slots (class)
45 (defmacro luna-define-class (type &optional parents slots)
46 "Define TYPE as a luna-class.
47 If PARENTS is specified, TYPE inherits PARENTS.
48 Each parent must be name of luna-class (symbol).
49 If SLOTS is specified, TYPE will be defined to have them."
50 (let ((oa (make-vector 31 0))
56 (setq parent (pop rest)
58 (mapatoms (lambda (sym)
59 (when (setq j (get sym 'luna-member-index))
60 (setq name (symbol-name sym))
61 (unless (intern-soft name oa)
62 (put (intern name oa) 'luna-member-index (+ j b))
65 (luna-class-obarray (luna-find-class parent)))
69 (setq name (symbol-name (pop rest)))
70 (unless (intern-soft name oa)
71 (put (intern name oa) 'luna-member-index i)
74 `(luna-set-class ',type
75 (vector 'class ,oa ',parents ,i))
78 (defmacro luna-class-name (entity)
79 "Return class-name of the ENTITY."
82 (defmacro luna-set-class-name (entity name)
83 `(aset ,entity 0 ,name))
85 (defmacro luna-get-obarray (entity)
88 (defmacro luna-set-obarray (entity obarray)
89 `(aset ,entity 1 ,obarray))
91 (defmacro luna-make-entity (type &rest init-args)
92 "Make instance of luna-class TYPE and return it.
93 If INIT-ARGS is specified, it is used as initial values of the slots.
94 It must be plist and each slot name must have prefix `:'."
95 `(apply #'luna-make-entity-function ',type ',init-args))
97 (defsubst luna-make-entity-function (type &rest init-args)
98 (let* ((c (get type 'luna-class))
99 (v (make-vector (luna-class-number-of-slots c) nil))
100 (oa (luna-class-obarray c))
102 (luna-set-class-name v type)
103 (luna-set-obarray v (make-vector 7 0))
105 (setq s (intern-soft (substring (symbol-name (pop init-args)) 1) oa)
108 (aset v (get s 'luna-member-index) i)
110 (luna-send v 'initialize-instance v)
113 (defsubst luna-class-find-member (class member-name)
114 (or (stringp member-name)
115 (setq member-name (symbol-name member-name)))
116 (or (intern-soft member-name (luna-class-obarray class))
117 (let ((parents (luna-class-parents class))
121 (setq ret (luna-class-find-member
122 (luna-find-class (pop parents))
126 (defsubst luna-class-find-or-make-member (class member-name)
127 (or (stringp member-name)
128 (setq member-name (symbol-name member-name)))
129 (intern member-name (luna-class-obarray class)))
131 (defmacro luna-class-slot-index (class slot-name)
132 `(get (luna-class-find-member ,class ,slot-name) 'luna-member-index))
134 (defmacro luna-slot-index (entity slot-name)
135 `(luna-class-slot-index (luna-find-class (luna-class-name ,entity))
138 (defsubst luna-slot-value (entity slot)
139 "Return the value of SLOT of ENTITY."
140 (aref entity (luna-slot-index entity slot)))
142 (defsubst luna-set-slot-value (entity slot value)
143 "Store VALUE into SLOT of ENTITY."
144 (aset entity (luna-slot-index entity slot) value))
146 (defmacro luna-define-method (name args &rest body)
147 "Define NAME as a method function of (nth 1 (car ARGS)) backend.
149 ARGS is like an argument list of lambda, but (car ARGS) must be
150 specialized parameter. (car (car ARGS)) is name of variable and (nth
151 1 (car ARGS)) is name of backend."
152 (let* ((specializer (car args))
153 (class (nth 1 specializer))
154 (self (car specializer)))
155 `(let ((func (lambda ,(if self
156 (cons self (cdr args))
159 (fset (luna-class-find-or-make-member (luna-find-class ',class) ',name)
162 (put 'luna-define-method 'lisp-indent-function 'defun)
164 (defsubst luna-class-find-function (class service)
165 (let ((sym (luna-class-find-member class service)))
167 (symbol-function sym)
168 (let ((parents (luna-class-parents class))
172 (setq ret (luna-class-find-function
173 (luna-find-class (pop parents))
177 (defmacro luna-find-function (entity service)
178 `(luna-class-find-function (luna-find-class (luna-class-name ,entity))
181 (defsubst luna-send (entity message &rest args)
182 "Send MESSAGE to ENTITY with ARGS, and return the result."
183 (apply (luna-find-function entity message)
186 (defsubst luna-arglist-to-arguments (arglist)
189 (let ((arg (car arglist)))
190 (or (memq arg '(&optional &rest))
191 (setq dest (cons arg dest)))
193 (setq arglist (cdr arglist)))
196 (defmacro luna-define-generic (name args &optional doc)
197 "Define generic-function NAME.
198 ARGS is argument of and DOC is DOC-string."
200 `(defun ,(intern (symbol-name name)) ,args
202 (luna-send ,(car args) ',name
203 ,@(luna-arglist-to-arguments (cdr args)))
205 `(defun ,(intern (symbol-name name)) ,args
206 (luna-send ,(car args) ',name
207 ,@(luna-arglist-to-arguments (cdr args)))
210 (put 'luna-define-generic 'lisp-indent-function 'defun)