source: branches/0.22.x/abcl/src/org/armedbear/lisp/Function.java

Last change on this file was 12826, checked in by vvoutilainen, 14 years ago

DocString? annotation support, for generating DOCUMENTATION, and
later Javadoc from the same data. Also includes TAGS support
for the DocString? annotations. Patch by Matt Seddon.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.2 KB
Line 
1/*
2 * Function.java
3 *
4 * Copyright (C) 2002-2005 Peter Graves
5 * $Id: Function.java 12826 2010-07-25 19:09:13Z vvoutilainen $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38public abstract class Function extends Operator
39{
40    private LispObject propertyList = NIL;
41    private int callCount;
42    private int hotCount;
43    /**
44     * The value of *load-truename* which was current when this function
45     * was loaded, used for fetching the class bytes in case of disassebly.
46     */
47    private final LispObject loadedFrom;
48
49    protected Function() {
50  LispObject loadTruename = Symbol.LOAD_TRUENAME.symbolValueNoThrow();
51  loadedFrom = loadTruename != null ? loadTruename : NIL;
52    }
53
54    public Function(String name)
55    {
56        this(name, (String)null);
57    }
58
59    public Function(String name, String arglist)
60    {
61  this();
62        if(arglist != null)
63            setLambdaList(new SimpleString(arglist));
64        if (name != null) {
65            Symbol symbol = Symbol.addFunction(name.toUpperCase(), this);
66            if (cold)
67                symbol.setBuiltInFunction(true);
68            setLambdaName(symbol);
69        }
70    }
71
72    public Function(Symbol symbol)
73    {
74  this(symbol, null, null);
75    }
76
77    public Function(Symbol symbol, String arglist)
78    {
79  this(symbol, arglist, null);
80    }
81
82    public Function(Symbol symbol, String arglist, String docstring)
83    {
84  this();
85        symbol.setSymbolFunction(this);
86        if (cold)
87            symbol.setBuiltInFunction(true);
88        setLambdaName(symbol);
89        if(arglist != null)
90            setLambdaList(new SimpleString(arglist));
91        if (docstring != null)
92            symbol.setDocumentation(Symbol.FUNCTION,
93                                    new SimpleString(docstring));
94    }
95
96    public Function(String name, Package pkg)
97    {
98        this(name, pkg, false);
99    }
100
101    public Function(String name, Package pkg, boolean exported)
102    {
103        this(name, pkg, exported, null, null);
104    }
105
106    public Function(String name, Package pkg, boolean exported,
107                    String arglist)
108    {
109        this(name, pkg, exported, arglist, null);
110    }
111
112    public Function(String name, Package pkg, boolean exported,
113                    String arglist, String docstring)
114    {
115  this();
116        if (arglist instanceof String)
117            setLambdaList(new SimpleString(arglist));
118        if (name != null) {
119            Symbol symbol;
120            if (exported)
121                symbol = pkg.internAndExport(name.toUpperCase());
122            else
123                symbol = pkg.intern(name.toUpperCase());
124            symbol.setSymbolFunction(this);
125            if (cold)
126                symbol.setBuiltInFunction(true);
127            setLambdaName(symbol);
128            if (docstring != null)
129                symbol.setDocumentation(Symbol.FUNCTION,
130                                        new SimpleString(docstring));
131        }
132    }
133
134    public Function(LispObject name)
135    {
136  this();
137        setLambdaName(name);
138    }
139
140    public Function(LispObject name, LispObject lambdaList)
141    {
142  this();
143        setLambdaName(name);
144        setLambdaList(lambdaList);
145    }
146
147    @Override
148    public LispObject typeOf()
149    {
150        return Symbol.FUNCTION;
151    }
152
153    @Override
154    public LispObject classOf()
155    {
156        return BuiltInClass.FUNCTION;
157    }
158
159    @Override
160    public LispObject typep(LispObject typeSpecifier)
161    {
162        if (typeSpecifier == Symbol.FUNCTION)
163            return T;
164        if (typeSpecifier == Symbol.COMPILED_FUNCTION)
165            return T;
166        if (typeSpecifier == BuiltInClass.FUNCTION)
167            return T;
168        return super.typep(typeSpecifier);
169    }
170
171    @Override
172    public final LispObject getPropertyList()
173    {
174        if (propertyList == null)
175            propertyList = NIL;
176        return propertyList;
177    }
178
179    @Override
180    public final void setPropertyList(LispObject obj)
181    {
182        if (obj == null)
183            throw new NullPointerException();
184        propertyList = obj;
185    }
186
187    public final void setClassBytes(byte[] bytes)
188    {
189        propertyList = putf(propertyList, Symbol.CLASS_BYTES,
190                            new JavaObject(bytes));
191    }
192
193    public final LispObject getClassBytes() {
194  LispObject o = getf(propertyList, Symbol.CLASS_BYTES, NIL);
195  if(o != NIL) {
196      return o;
197  } else {
198      ClassLoader c = getClass().getClassLoader();
199      if(c instanceof FaslClassLoader) {
200    final LispThread thread = LispThread.currentThread(); 
201    SpecialBindingsMark mark = thread.markSpecialBindings(); 
202    try { 
203        thread.bindSpecial(Symbol.LOAD_TRUENAME, loadedFrom); 
204        return new JavaObject(((FaslClassLoader) c).getFunctionClassBytes(this));
205    } catch(Throwable t) {
206        //This is because unfortunately getFunctionClassBytes uses
207        //Debug.assertTrue(false) to signal errors
208        if(t instanceof ControlTransfer) {
209      throw (ControlTransfer) t;
210        } else {
211      return NIL;
212        }
213    } finally { 
214        thread.resetSpecialBindings(mark); 
215    }   
216      } else {
217    return NIL;
218      }
219  }
220    }
221
222    public static final Primitive FUNCTION_CLASS_BYTES = new pf_function_class_bytes();
223    public static final class pf_function_class_bytes extends Primitive {
224  public pf_function_class_bytes() {
225      super("function-class-bytes", PACKAGE_SYS, false, "function");
226        }
227        @Override
228        public LispObject execute(LispObject arg) {
229            if (arg instanceof Function) {
230                return ((Function) arg).getClassBytes();
231      }
232            return type_error(arg, Symbol.FUNCTION);
233        }
234    }
235
236    @Override
237    public LispObject execute()
238    {
239        return error(new WrongNumberOfArgumentsException(this, 0));
240    }
241
242    @Override
243    public LispObject execute(LispObject arg)
244    {
245        return error(new WrongNumberOfArgumentsException(this, 1));
246    }
247
248    @Override
249    public LispObject execute(LispObject first, LispObject second)
250
251    {
252        return error(new WrongNumberOfArgumentsException(this, 2));
253    }
254
255    @Override
256    public LispObject execute(LispObject first, LispObject second,
257                              LispObject third)
258
259    {
260        return error(new WrongNumberOfArgumentsException(this, 3));
261    }
262
263    @Override
264    public LispObject execute(LispObject first, LispObject second,
265                              LispObject third, LispObject fourth)
266
267    {
268        return error(new WrongNumberOfArgumentsException(this, 4));
269    }
270
271    @Override
272    public LispObject execute(LispObject first, LispObject second,
273                              LispObject third, LispObject fourth,
274                              LispObject fifth)
275
276    {
277        return error(new WrongNumberOfArgumentsException(this, 5));
278    }
279
280    @Override
281    public LispObject execute(LispObject first, LispObject second,
282                              LispObject third, LispObject fourth,
283                              LispObject fifth, LispObject sixth)
284
285    {
286        return error(new WrongNumberOfArgumentsException(this, 6));
287    }
288
289    @Override
290    public LispObject execute(LispObject first, LispObject second,
291                              LispObject third, LispObject fourth,
292                              LispObject fifth, LispObject sixth,
293                              LispObject seventh)
294
295    {
296        return error(new WrongNumberOfArgumentsException(this, 7));
297    }
298
299    @Override
300    public LispObject execute(LispObject first, LispObject second,
301                              LispObject third, LispObject fourth,
302                              LispObject fifth, LispObject sixth,
303                              LispObject seventh, LispObject eighth)
304
305    {
306        return error(new WrongNumberOfArgumentsException(this, 8));
307    }
308
309    @Override
310    public LispObject execute(LispObject[] args)
311    {
312        return error(new WrongNumberOfArgumentsException(this));
313    }
314
315    @Override
316    public String writeToString()
317    {
318        LispObject name = getLambdaName();
319        if (name != null && name != NIL) {
320            StringBuffer sb = new StringBuffer("#<FUNCTION ");
321            sb.append(name.writeToString());
322            sb.append(" {");
323            sb.append(Integer.toHexString(System.identityHashCode(this)).toUpperCase());
324            sb.append("}>");
325            return sb.toString();
326        }
327        // No name.
328        LispObject lambdaList = getLambdaList();
329        if (lambdaList != null) {
330            StringBuffer sb = new StringBuffer("#<FUNCTION ");
331            sb.append("(LAMBDA ");
332            if (lambdaList == NIL) {
333                sb.append("()");
334            } else {
335                final LispThread thread = LispThread.currentThread();
336                final SpecialBindingsMark mark = thread.markSpecialBindings();
337                thread.bindSpecial(Symbol.PRINT_LENGTH, Fixnum.THREE);
338                try {
339                    sb.append(lambdaList.writeToString());
340                }
341                finally {
342                    thread.resetSpecialBindings(mark);
343                }
344            }
345            sb.append(")");
346            sb.append(" {");
347            sb.append(Integer.toHexString(System.identityHashCode(this)).toUpperCase());
348            sb.append("}>");
349            return sb.toString();
350        }
351        return unreadableString("FUNCTION");
352    }
353
354    // Used by the JVM compiler.
355    public final void argCountError()
356    {
357        error(new WrongNumberOfArgumentsException(this));
358    }
359
360    // Profiling.
361    @Override
362    public final int getCallCount()
363    {
364        return callCount;
365    }
366
367    @Override
368    public void setCallCount(int n)
369    {
370        callCount = n;
371    }
372
373    @Override
374    public final void incrementCallCount()
375    {
376        ++callCount;
377    }
378
379    @Override
380    public final int getHotCount()
381    {
382        return hotCount;
383    }
384
385    @Override
386    public void setHotCount(int n)
387    {
388        hotCount = n;
389    }
390
391    @Override
392    public final void incrementHotCount()
393    {
394        ++hotCount;
395    }
396}
Note: See TracBrowser for help on using the repository browser.