source: branches/0.17.x/abcl/src/org/armedbear/lisp/Environment.java

Last change on this file was 12254, checked in by ehuelsmann, 16 years ago

Remove 'throws ConditionThrowable?' method annotations:

it's an unchecked exception now, so no need to declare it thrown.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.5 KB
Line 
1/*
2 * Environment.java
3 *
4 * Copyright (C) 2002-2006 Peter Graves
5 * $Id: Environment.java 12254 2009-11-06 20:07:54Z ehuelsmann $
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
36public final class Environment extends LispObject
37{
38  private Binding vars;
39  private FunctionBinding lastFunctionBinding;
40  private Binding blocks;
41  private Binding tags;
42  public boolean inactive; //default value: false == active
43
44  public Environment() {}
45
46  public Environment(Environment parent)
47  {
48    if (parent != null)
49      {
50        vars = parent.vars;
51        lastFunctionBinding = parent.lastFunctionBinding;
52        blocks = parent.blocks;
53        tags = parent.tags;
54      }
55  }
56
57  // Construct a new Environment extending parent with the specified symbol-
58  // value binding.
59  public Environment(Environment parent, Symbol symbol, LispObject value)
60  {
61    this(parent);
62    vars = new Binding(symbol, value, vars);
63  }
64
65  @Override
66  public LispObject typeOf()
67  {
68    return Symbol.ENVIRONMENT;
69  }
70
71  @Override
72  public LispObject classOf()
73  {
74    return BuiltInClass.ENVIRONMENT;
75  }
76
77  @Override
78  public LispObject typep(LispObject type)
79  {
80    if (type == Symbol.ENVIRONMENT)
81      return T;
82    if (type == BuiltInClass.ENVIRONMENT)
83      return T;
84    return super.typep(type);
85  }
86
87  public boolean isEmpty()
88  {
89    if (lastFunctionBinding != null)
90      return false;
91    if (vars != null)
92      {
93        for (Binding binding = vars; binding != null; binding = binding.next)
94          if (!binding.specialp)
95            return false;
96      }
97    return true;
98  }
99
100  public void bind(Symbol symbol, LispObject value)
101  {
102    vars = new Binding(symbol, value, vars);
103  }
104
105  public void rebind(Symbol symbol, LispObject value)
106  {
107    Binding binding = getBinding(symbol);
108    binding.value = value;
109  }
110
111  public LispObject lookup(LispObject symbol)
112  {
113    Binding binding = vars;
114    while (binding != null)
115      {
116        if (binding.symbol == symbol)
117          return binding.value;
118        binding = binding.next;
119      }
120    return null;
121  }
122
123  public Binding getBinding(LispObject symbol)
124  {
125    Binding binding = vars;
126    while (binding != null)
127      {
128        if (binding.symbol == symbol)
129          return binding;
130        binding = binding.next;
131      }
132    return null;
133  }
134
135  // Function bindings.
136  public void addFunctionBinding(LispObject name, LispObject value)
137  {
138    lastFunctionBinding =
139      new FunctionBinding(name, value, lastFunctionBinding);
140  }
141
142  public LispObject lookupFunction(LispObject name)
143
144  {
145    FunctionBinding binding = lastFunctionBinding;
146    if (name instanceof Symbol)
147      {
148        while (binding != null)
149          {
150            if (binding.name == name)
151              return binding.value;
152            binding = binding.next;
153          }
154        // Not found in environment.
155        return name.getSymbolFunction();
156      }
157    if (name instanceof Cons)
158      {
159        while (binding != null)
160          {
161            if (binding.name.equal(name))
162              return binding.value;
163            binding = binding.next;
164          }
165      }
166    return null;
167  }
168
169  public void addBlock(LispObject symbol, LispObject block)
170  {
171    blocks = new Binding(symbol, this, block, blocks);
172  }
173
174  public LispObject lookupBlock(LispObject symbol)
175  {
176    Binding binding = blocks;
177    while (binding != null)
178      {
179        if (binding.symbol == symbol)
180          return binding.value;
181        binding = binding.next;
182      }
183    return null;
184  }
185
186  public Binding getBlockBinding(LispObject block)
187  {
188    Binding binding = blocks;
189    while (binding != null)
190      {
191        if (binding.symbol == block)
192          return binding;
193        binding = binding.next;
194      }
195    return null;
196  }
197
198  public void addTagBinding(LispObject tag, LispObject code)
199  {
200    tags = new Binding(tag, this, code, tags);
201  }
202
203  public Binding getTagBinding(LispObject tag)
204  {
205    Binding binding = tags;
206    while (binding != null)
207      {
208        if (binding.symbol.eql(tag))
209          return binding;
210        binding = binding.next;
211      }
212    return null;
213  }
214
215  // Returns body with declarations removed.
216  public LispObject processDeclarations(LispObject body)
217
218  {
219    LispObject bodyAndDecls = parseBody(body, false);
220    LispObject specials = parseSpecials(bodyAndDecls.NTH(1));
221    for (; specials != NIL; specials = specials.cdr())
222      declareSpecial(checkSymbol(specials.car()));
223
224    return bodyAndDecls.car();
225  }
226
227  public void declareSpecial(Symbol var)
228  {
229    vars = new Binding(var, null, vars);
230    vars.specialp = true;
231  }
232
233    /** Return true if a symbol is declared special.
234     *
235     * If there is no binding in the current (lexical) environment,
236     * the current dynamic environment (thread) is checked.
237     */
238  public boolean isDeclaredSpecial(LispObject var)
239  {
240    Binding binding = getBinding(var);
241    return (binding != null) ? binding.specialp :
242        (LispThread.currentThread().getSpecialBinding(var) != null);
243  }
244
245  @Override
246  public String writeToString()
247  {
248    return unreadableString(Symbol.ENVIRONMENT);
249  }
250
251  // ### make-environment
252  public static final Primitive MAKE_ENVIRONMENT =
253    new Primitive("make-environment", PACKAGE_SYS, true,
254                  "&optional parent-environment")
255    {
256      @Override
257      public LispObject execute()
258      {
259        return new Environment();
260      }
261      @Override
262      public LispObject execute(LispObject arg)
263      {
264        if (arg == NIL)
265          return new Environment();
266        return new Environment(checkEnvironment(arg));
267      }
268    };
269
270  // ### environment-add-macro-definition
271  public static final Primitive ENVIRONMENT_ADD_MACRO_DEFINITION =
272    new Primitive("environment-add-macro-definition", PACKAGE_SYS, true,
273                  "environment name expander")
274    {
275      @Override
276      public LispObject execute(LispObject first, LispObject second,
277                                LispObject third)
278
279      {
280        Environment env = checkEnvironment(first);
281        LispObject name = second;
282        LispObject expander = third;
283        env.addFunctionBinding(name, expander);
284        return env;
285      }
286    };
287
288  // ### environment-add-function-definition
289  public static final Primitive ENVIRONMENT_ADD_FUNCTION_DEFINITION =
290    new Primitive("environment-add-function-definition", PACKAGE_SYS, true,
291                  "environment name lambda-expression")
292    {
293      @Override
294      public LispObject execute(LispObject first, LispObject second,
295                                LispObject third)
296
297      {
298        checkEnvironment(first).addFunctionBinding(second, third);
299        return first;
300      }
301    };
302
303  // ### environment-add-symbol-binding
304  public static final Primitive ENVIRONMENT_ADD_SYMBOL_BINDING =
305    new Primitive("environment-add-symbol-binding", PACKAGE_SYS, true,
306                  "environment symbol value")
307    {
308      @Override
309      public LispObject execute(LispObject first, LispObject second,
310                                LispObject third)
311
312      {
313        checkEnvironment(first).bind(checkSymbol(second), third);
314        return first;
315      }
316    };
317
318  // ### empty-environment-p
319  private static final Primitive EMPTY_ENVIRONMENT_P =
320    new Primitive("empty-environment-p", PACKAGE_SYS, true, "environment")
321    {
322      @Override
323      public LispObject execute(LispObject arg)
324      {
325          return checkEnvironment(arg).isEmpty() ? T : NIL;
326      }
327    };
328
329  // ### environment-variables
330  private static final Primitive ENVIRONMENT_VARS =
331    new Primitive("environment-variables", PACKAGE_SYS, true, "environment")
332    {
333      @Override
334      public LispObject execute(LispObject arg)
335      {
336            Environment env = checkEnvironment(arg);
337            LispObject result = NIL;
338            for (Binding binding = env.vars; binding != null; binding = binding.next)
339              if (!binding.specialp)
340                result = result.push(new Cons(binding.symbol, binding.value));
341            return result.nreverse();
342      }
343    };
344
345  // ### environment-all-variables
346  private static final Primitive ENVIRONMENT_ALL_VARS =
347    new Primitive("environment-all-variables", PACKAGE_SYS, true, "environment")
348    {
349      @Override
350      public LispObject execute(LispObject arg)
351      {
352            Environment env = checkEnvironment(arg);
353            LispObject result = NIL;
354            for (Binding binding = env.vars;
355                 binding != null; binding = binding.next)
356              if (binding.specialp)
357                result = result.push(binding.symbol);
358              else
359                result = result.push(new Cons(binding.symbol, binding.value));
360            return result.nreverse();
361      }
362    };
363
364  // ### environment-all-functions
365  private static final Primitive ENVIRONMENT_ALL_FUNS =
366    new Primitive("environment-all-functions", PACKAGE_SYS, true, "environment")
367    {
368      @Override
369      public LispObject execute(LispObject arg)
370      {
371            Environment env = checkEnvironment(arg);
372            LispObject result = NIL;
373            for (FunctionBinding binding = env.lastFunctionBinding;
374                 binding != null; binding = binding.next)
375            result = result.push(new Cons(binding.name, binding.value));
376            return result.nreverse();
377      }
378    };
379}
Note: See TracBrowser for help on using the repository browser.