Package org.jatha.compile.args

Source Code of org.jatha.compile.args.OrdinaryLambdaList

/*
* Jatha - a Common LISP-compatible LISP library in Java.
* Copyright (C) 1997-2005 Micheal Scott Hewett
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
* For further information, please contact Micheal Hewett at
*   hewett@cs.stanford.edu
*
*/
/**
* $Id: OrdinaryLambdaList.java,v 1.2 2005/05/21 16:28:46 olagus Exp $
*/
package org.jatha.compile.args;

import java.util.List;
import java.util.Map;
import java.util.LinkedList;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

import org.jatha.Jatha;

import org.jatha.dynatype.LispValue;

/**
* <p>Info about this class</p>
*
* @author <a href="mailto:Ola.Bini@itc.ki.se">Ola Bini</a>
* @version $Revision: 1.2 $
*/
public class OrdinaryLambdaList implements LambdaList {
    private Jatha lisp;

    private List normalArguments;
    private List optionalArguments;
    private RestArgument restArgument;
    private Map keyArguments;
    private boolean allowOtherKeys;
    private List auxArguments;

    private LispValue allowOtherKeysKey;

    public OrdinaryLambdaList(final Jatha lisp) {
        this.lisp = lisp;
        normalArguments = new LinkedList();
        optionalArguments = new LinkedList();
        restArgument = null;
        keyArguments = new HashMap();
        allowOtherKeys = false;
        auxArguments = new LinkedList();
        allowOtherKeysKey = lisp.EVAL.intern(":ALLOW-OTHER-KEYS");
    }

    public Map parse(final LispValue arguments) {
        final Map ret = new HashMap();
        int state = 0; // 0 = regular, 1 = optional, 2 = rest, 3 = key
        final Set keyArgsLeft = new HashSet(keyArguments.keySet());
        final Set optArgsLeft = new HashSet(optionalArguments);
        LispValue vals = lisp.NIL;
           
        Iterator next = normalArguments.iterator();
        LispValue rests = null;
        boolean tempAllow = allowOtherKeys;

        if(!tempAllow) {
            for(final Iterator iter = arguments.iterator();iter.hasNext();) {
                if((((LispValue)iter.next()).eql(allowOtherKeysKey)) == lisp.T && iter.next() != lisp.NIL) {
                    tempAllow = true;
                    break;
                }
            }
        }
       
        for(final Iterator iter = arguments.iterator();iter.hasNext();) {
            final LispValue val = (LispValue)iter.next();
            if(tempAllow && (val.eql(allowOtherKeysKey) == lisp.T)) {
                iter.next();
                continue;
            }

            while(next != null && !next.hasNext()) {
                state++;
                switch(state) {
                case 1:
                    next = optionalArguments.iterator();
                    break;
                case 2:
                    if(restArgument != null) {
                        rests = lisp.NIL;
                    }
                    next = null;
                    break;
                default:
                    next = null;
                    break;
                }
            }
            switch(state) {
            case 0:
                final NormalArgument arg = (NormalArgument)next.next();
                ret.put(arg.getVar(),val);
                vals = lisp.makeCons(lisp.makeList(arg.getVar(),val),vals);
                break;
            case 1:
                final OptionalArgument oarg = (OptionalArgument)next.next();
                ret.put(oarg.getVar(),val);
                vals = lisp.makeCons(lisp.makeList(oarg.getVar(),val),vals);
                optArgsLeft.remove(oarg);
                if(oarg.getSupplied() != null) {
                    ret.put(oarg.getSupplied(),lisp.T);
                    vals = lisp.makeCons(lisp.makeList(oarg.getSupplied(),lisp.T),vals);
                }
                break;
            default:
                if(keyArguments.size() > 0 || tempAllow) {
                    final KeyArgument key = (KeyArgument)keyArguments.get(val);
                    if(null != key || tempAllow) {
                        keyArgsLeft.remove(val);
                        final LispValue theVal = (LispValue)iter.next();
                        if(null != rests) {
                            rests = rests.append(lisp.makeCons(val,lisp.makeCons(theVal,lisp.NIL)));
                        }
                        if(null != key) {
                            ret.put(key.getVar(),theVal);
                            vals = lisp.makeCons(lisp.makeList(key.getVar(),theVal),vals);
                            if(key.getSupplied() != null) {
                                ret.put(key.getSupplied(),lisp.T);
                                vals = lisp.makeCons(lisp.makeList(key.getSupplied(),lisp.T),vals);
                            }
                        }
                    } else {
                        throw new IllegalArgumentException("Bad key argument: " + val); //TODO: fix good exception here
                    }
                } else if(null != rests) {
                    rests = rests.append(lisp.makeCons(val,lisp.NIL));
                } else {
                    throw new IllegalArgumentException("Bad arguments"); //TODO: fix good exception here
                }



                break;
            }
        }
        if(state == 0 && !optionalArguments.isEmpty()) {
            next = optionalArguments.iterator();
        }
        for(;next != null && next.hasNext();) {
            final OptionalArgument arg = (OptionalArgument)next.next();
            if(arg.getInitForm() != null) {
                final LispValue val = lisp.eval(arg.getInitForm(),lisp.makeList(vals));
                ret.put(arg.getVar(),val);
                vals = lisp.makeCons(lisp.makeList(arg.getVar(),val),vals);
            } else {
                ret.put(arg.getVar(),lisp.NIL);
                vals = lisp.makeCons(lisp.makeList(arg.getVar(),lisp.NIL),vals);
            }
            if(arg.getSupplied() != null) {
                ret.put(arg.getSupplied(),lisp.NIL);
                vals = lisp.makeCons(lisp.makeList(arg.getSupplied(),lisp.NIL),vals);
            }
        }
        for(final Iterator iter = keyArgsLeft.iterator();iter.hasNext();) {
            final LispValue sym = (LispValue)iter.next();
            final KeyArgument arg = (KeyArgument)keyArguments.get(sym);
            if(arg.getInitForm() != null) {
                final LispValue val = lisp.eval(arg.getInitForm(),lisp.makeList(vals));
                ret.put(arg.getVar(),val);
                vals = lisp.makeCons(lisp.makeList(arg.getVar(),val),vals);
            } else {
                ret.put(arg.getVar(),lisp.NIL);
                vals = lisp.makeCons(lisp.makeList(arg.getVar(),lisp.NIL),vals);
            }
            if(arg.getSupplied() != null) {
                ret.put(arg.getSupplied(),lisp.NIL);
                vals = lisp.makeCons(lisp.makeList(arg.getSupplied(),lisp.NIL),vals);
            }
        }
        if(restArgument != null) {
            if(rests != null) {
                ret.put(restArgument.getVar(),rests);
                vals = lisp.makeCons(lisp.makeList(restArgument.getVar(),rests),vals);
            } else {
                ret.put(restArgument.getVar(),lisp.NIL);
                vals = lisp.makeCons(lisp.makeList(restArgument.getVar(),lisp.NIL),vals);
            }
        }

        for(final Iterator iter = auxArguments.iterator();iter.hasNext();) {
            final AuxArgument arg = (AuxArgument)iter.next();
            final LispValue val = lisp.eval(arg.getInitForm(),lisp.makeList(vals));
            ret.put(arg.getVar(),val);
            vals = lisp.makeCons(lisp.makeList(arg.getVar(),val),vals);
        }
        return ret;
    }

    public List getNormalArguments() {
        return normalArguments;
    }

    public List getOptionalArguments() {
        return optionalArguments;
    }

    public RestArgument getRestArgument() {
        return restArgument;
    }

    public void setRestArgument(final RestArgument restArgument) {
        this.restArgument = restArgument;
    }

    public boolean getAllowOtherKeys() {
        return allowOtherKeys;
    }

    public void setAllowOtherKeys(final boolean allowOtherKeys) {
        this.allowOtherKeys = allowOtherKeys;
    }

    public Map getKeyArguments() {
        return keyArguments;
    }

    public List getAuxArguments() {
        return auxArguments;
    }
}// OrdinaryLambdaList
TOP

Related Classes of org.jatha.compile.args.OrdinaryLambdaList

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.