001: /*
002: * Jatha - a Common LISP-compatible LISP library in Java.
003: * Copyright (C) 1997-2005 Micheal Scott Hewett
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: *
020: * For further information, please contact Micheal Hewett at
021: * hewett@cs.stanford.edu
022: *
023: */
024: /**
025: * $Id: OrdinaryLambdaList.java,v 1.2 2005/05/21 16:28:46 olagus Exp $
026: */package org.jatha.compile.args;
027:
028: import java.util.List;
029: import java.util.Map;
030: import java.util.LinkedList;
031: import java.util.HashMap;
032: import java.util.Set;
033: import java.util.HashSet;
034: import java.util.Iterator;
035:
036: import org.jatha.Jatha;
037:
038: import org.jatha.dynatype.LispValue;
039:
040: /**
041: * <p>Info about this class</p>
042: *
043: * @author <a href="mailto:Ola.Bini@itc.ki.se">Ola Bini</a>
044: * @version $Revision: 1.2 $
045: */
046: public class OrdinaryLambdaList implements LambdaList {
047: private Jatha lisp;
048:
049: private List normalArguments;
050: private List optionalArguments;
051: private RestArgument restArgument;
052: private Map keyArguments;
053: private boolean allowOtherKeys;
054: private List auxArguments;
055:
056: private LispValue allowOtherKeysKey;
057:
058: public OrdinaryLambdaList(final Jatha lisp) {
059: this .lisp = lisp;
060: normalArguments = new LinkedList();
061: optionalArguments = new LinkedList();
062: restArgument = null;
063: keyArguments = new HashMap();
064: allowOtherKeys = false;
065: auxArguments = new LinkedList();
066: allowOtherKeysKey = lisp.EVAL.intern(":ALLOW-OTHER-KEYS");
067: }
068:
069: public Map parse(final LispValue arguments) {
070: final Map ret = new HashMap();
071: int state = 0; // 0 = regular, 1 = optional, 2 = rest, 3 = key
072: final Set keyArgsLeft = new HashSet(keyArguments.keySet());
073: final Set optArgsLeft = new HashSet(optionalArguments);
074: LispValue vals = lisp.NIL;
075:
076: Iterator next = normalArguments.iterator();
077: LispValue rests = null;
078: boolean tempAllow = allowOtherKeys;
079:
080: if (!tempAllow) {
081: for (final Iterator iter = arguments.iterator(); iter
082: .hasNext();) {
083: if ((((LispValue) iter.next()).eql(allowOtherKeysKey)) == lisp.T
084: && iter.next() != lisp.NIL) {
085: tempAllow = true;
086: break;
087: }
088: }
089: }
090:
091: for (final Iterator iter = arguments.iterator(); iter.hasNext();) {
092: final LispValue val = (LispValue) iter.next();
093: if (tempAllow && (val.eql(allowOtherKeysKey) == lisp.T)) {
094: iter.next();
095: continue;
096: }
097:
098: while (next != null && !next.hasNext()) {
099: state++;
100: switch (state) {
101: case 1:
102: next = optionalArguments.iterator();
103: break;
104: case 2:
105: if (restArgument != null) {
106: rests = lisp.NIL;
107: }
108: next = null;
109: break;
110: default:
111: next = null;
112: break;
113: }
114: }
115: switch (state) {
116: case 0:
117: final NormalArgument arg = (NormalArgument) next.next();
118: ret.put(arg.getVar(), val);
119: vals = lisp.makeCons(lisp.makeList(arg.getVar(), val),
120: vals);
121: break;
122: case 1:
123: final OptionalArgument oarg = (OptionalArgument) next
124: .next();
125: ret.put(oarg.getVar(), val);
126: vals = lisp.makeCons(lisp.makeList(oarg.getVar(), val),
127: vals);
128: optArgsLeft.remove(oarg);
129: if (oarg.getSupplied() != null) {
130: ret.put(oarg.getSupplied(), lisp.T);
131: vals = lisp.makeCons(lisp.makeList(oarg
132: .getSupplied(), lisp.T), vals);
133: }
134: break;
135: default:
136: if (keyArguments.size() > 0 || tempAllow) {
137: final KeyArgument key = (KeyArgument) keyArguments
138: .get(val);
139: if (null != key || tempAllow) {
140: keyArgsLeft.remove(val);
141: final LispValue theVal = (LispValue) iter
142: .next();
143: if (null != rests) {
144: rests = rests.append(lisp.makeCons(val,
145: lisp.makeCons(theVal, lisp.NIL)));
146: }
147: if (null != key) {
148: ret.put(key.getVar(), theVal);
149: vals = lisp.makeCons(lisp.makeList(key
150: .getVar(), theVal), vals);
151: if (key.getSupplied() != null) {
152: ret.put(key.getSupplied(), lisp.T);
153: vals = lisp.makeCons(lisp.makeList(key
154: .getSupplied(), lisp.T), vals);
155: }
156: }
157: } else {
158: throw new IllegalArgumentException(
159: "Bad key argument: " + val); //TODO: fix good exception here
160: }
161: } else if (null != rests) {
162: rests = rests.append(lisp.makeCons(val, lisp.NIL));
163: } else {
164: throw new IllegalArgumentException("Bad arguments"); //TODO: fix good exception here
165: }
166:
167: break;
168: }
169: }
170: if (state == 0 && !optionalArguments.isEmpty()) {
171: next = optionalArguments.iterator();
172: }
173: for (; next != null && next.hasNext();) {
174: final OptionalArgument arg = (OptionalArgument) next.next();
175: if (arg.getInitForm() != null) {
176: final LispValue val = lisp.eval(arg.getInitForm(), lisp
177: .makeList(vals));
178: ret.put(arg.getVar(), val);
179: vals = lisp.makeCons(lisp.makeList(arg.getVar(), val),
180: vals);
181: } else {
182: ret.put(arg.getVar(), lisp.NIL);
183: vals = lisp.makeCons(lisp.makeList(arg.getVar(),
184: lisp.NIL), vals);
185: }
186: if (arg.getSupplied() != null) {
187: ret.put(arg.getSupplied(), lisp.NIL);
188: vals = lisp.makeCons(lisp.makeList(arg.getSupplied(),
189: lisp.NIL), vals);
190: }
191: }
192: for (final Iterator iter = keyArgsLeft.iterator(); iter
193: .hasNext();) {
194: final LispValue sym = (LispValue) iter.next();
195: final KeyArgument arg = (KeyArgument) keyArguments.get(sym);
196: if (arg.getInitForm() != null) {
197: final LispValue val = lisp.eval(arg.getInitForm(), lisp
198: .makeList(vals));
199: ret.put(arg.getVar(), val);
200: vals = lisp.makeCons(lisp.makeList(arg.getVar(), val),
201: vals);
202: } else {
203: ret.put(arg.getVar(), lisp.NIL);
204: vals = lisp.makeCons(lisp.makeList(arg.getVar(),
205: lisp.NIL), vals);
206: }
207: if (arg.getSupplied() != null) {
208: ret.put(arg.getSupplied(), lisp.NIL);
209: vals = lisp.makeCons(lisp.makeList(arg.getSupplied(),
210: lisp.NIL), vals);
211: }
212: }
213: if (restArgument != null) {
214: if (rests != null) {
215: ret.put(restArgument.getVar(), rests);
216: vals = lisp.makeCons(lisp.makeList(restArgument
217: .getVar(), rests), vals);
218: } else {
219: ret.put(restArgument.getVar(), lisp.NIL);
220: vals = lisp.makeCons(lisp.makeList(restArgument
221: .getVar(), lisp.NIL), vals);
222: }
223: }
224:
225: for (final Iterator iter = auxArguments.iterator(); iter
226: .hasNext();) {
227: final AuxArgument arg = (AuxArgument) iter.next();
228: final LispValue val = lisp.eval(arg.getInitForm(), lisp
229: .makeList(vals));
230: ret.put(arg.getVar(), val);
231: vals = lisp
232: .makeCons(lisp.makeList(arg.getVar(), val), vals);
233: }
234: return ret;
235: }
236:
237: public List getNormalArguments() {
238: return normalArguments;
239: }
240:
241: public List getOptionalArguments() {
242: return optionalArguments;
243: }
244:
245: public RestArgument getRestArgument() {
246: return restArgument;
247: }
248:
249: public void setRestArgument(final RestArgument restArgument) {
250: this .restArgument = restArgument;
251: }
252:
253: public boolean getAllowOtherKeys() {
254: return allowOtherKeys;
255: }
256:
257: public void setAllowOtherKeys(final boolean allowOtherKeys) {
258: this .allowOtherKeys = allowOtherKeys;
259: }
260:
261: public Map getKeyArguments() {
262: return keyArguments;
263: }
264:
265: public List getAuxArguments() {
266: return auxArguments;
267: }
268: }// OrdinaryLambdaList
|