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

Last change on this file was 13374, checked in by Mark Evenson, 14 years ago

Correct mispelling.

  • 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 13374 2011-07-04 14:03:43Z mevenson $
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 disassembly.
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.