source: branches/0.15.x/abcl/src/org/armedbear/lisp/dolist.java

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

Factor out functions to separate declarations, the body and optionally the
documentation as well as to determine which variables have been declared
special.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.9 KB
Line 
1/*
2 * dolist.java
3 *
4 * Copyright (C) 2003-2006 Peter Graves
5 * $Id: dolist.java 11772 2009-04-20 20:21:37Z 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
36// ### dolist
37public final class dolist extends SpecialOperator
38{
39  private dolist()
40  {
41    super(Symbol.DOLIST);
42  }
43
44  @Override
45  public LispObject execute(LispObject args, Environment env)
46    throws ConditionThrowable
47  {
48    LispObject bodyForm = args.cdr();
49    args = args.car();
50    Symbol var = checkSymbol(args.car());
51    LispObject listForm = args.cadr();
52    final LispThread thread = LispThread.currentThread();
53    LispObject resultForm = args.cdr().cdr().car();
54    SpecialBinding lastSpecialBinding = thread.lastSpecialBinding;
55    final LispObject stack = thread.getStack();
56    // Process declarations.
57    LispObject bodyAndDecls = parseBody(bodyForm, false);
58    LispObject specials = parseSpecials(bodyAndDecls.NTH(1));
59    bodyForm = bodyAndDecls.car();
60
61    try
62      {
63        final Environment ext = new Environment(env);
64        // Implicit block.
65        ext.addBlock(NIL, new LispObject());
66        // Evaluate the list form.
67        LispObject list = checkList(eval(listForm, ext, thread));
68        // Look for tags.
69        LispObject remaining = bodyForm;
70        while (remaining != NIL)
71          {
72            LispObject current = remaining.car();
73            remaining = remaining.cdr();
74            if (current instanceof Cons)
75              continue;
76            // It's a tag.
77            ext.addTagBinding(current, remaining);
78          }
79        // Establish a reusable binding.
80        final Object binding;
81        if (specials != NIL && memq(var, specials))
82          {
83            thread.bindSpecial(var, null);
84            binding = thread.getSpecialBinding(var);
85            ext.declareSpecial(var);
86          }
87        else if (var.isSpecialVariable())
88          {
89            thread.bindSpecial(var, null);
90            binding = thread.getSpecialBinding(var);
91          }
92        else
93          {
94            ext.bind(var, null);
95            binding = ext.getBinding(var);
96          }
97        while (specials != NIL)
98          {
99            ext.declareSpecial(checkSymbol(specials.car()));
100            specials = specials.cdr();
101          }
102        while (list != NIL)
103          {
104            if (binding instanceof SpecialBinding)
105              ((SpecialBinding)binding).value = list.car();
106            else
107              ((Binding)binding).value = list.car();
108            LispObject body = bodyForm;
109            while (body != NIL)
110              {
111                LispObject current = body.car();
112                if (current instanceof Cons)
113                  {
114                    try
115                      {
116                        // Handle GO inline if possible.
117                        if (current.car() == Symbol.GO)
118                          {
119                            LispObject tag = current.cadr();
120                            Binding b = ext.getTagBinding(tag);
121                            if (b != null && b.value != null)
122                              {
123                                body = b.value;
124                                continue;
125                              }
126                            throw new Go(tag);
127                          }
128                        eval(current, ext, thread);
129                      }
130                    catch (Go go)
131                      {
132                        LispObject tag = go.getTag();
133                        Binding b = ext.getTagBinding(tag);
134                        if (b != null && b.value != null)
135                          {
136                            body = b.value;
137                            thread.setStack(stack);
138                            continue;
139                          }
140                        throw go;
141                      }
142                  }
143                body = body.cdr();
144              }
145            list = list.cdr();
146            if (interrupted)
147              handleInterrupt();
148          }
149        if (binding instanceof SpecialBinding)
150          ((SpecialBinding)binding).value = NIL;
151        else
152          ((Binding)binding).value = NIL;
153        LispObject result = eval(resultForm, ext, thread);
154        return result;
155      }
156    catch (Return ret)
157      {
158        if (ret.getTag() == NIL)
159          {
160            thread.setStack(stack);
161            return ret.getResult();
162          }
163        throw ret;
164      }
165    finally
166      {
167        thread.lastSpecialBinding = lastSpecialBinding;
168      }
169  }
170
171  private static final dolist DOLIST = new dolist();
172}
Note: See TracBrowser for help on using the repository browser.