All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jaitools.jiffle.parser.FunctionLookup Maven / Gradle / Ivy

/* 
 *  Copyright (c) 2011, Michael Bedward. All rights reserved. 
 *   
 *  Redistribution and use in source and binary forms, with or without modification, 
 *  are permitted provided that the following conditions are met: 
 *   
 *  - Redistributions of source code must retain the above copyright notice, this  
 *    list of conditions and the following disclaimer. 
 *   
 *  - Redistributions in binary form must reproduce the above copyright notice, this 
 *    list of conditions and the following disclaimer in the documentation and/or 
 *    other materials provided with the distribution.   
 *   
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
 *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */   

package org.jaitools.jiffle.parser;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.jaitools.CollectionFactory;

/**
 * A lookup service used by the Jiffle compiler when parsing function
 * calls in scripts.
 * 
 * @author Michael Bedward
 * @since 0.1
 * @version $Id$
 */
public class FunctionLookup {

    private static final String PROPERTIES_FILE = 
            "META-INF/org/jaitools/jiffle/FunctionLookup.properties";

    private static final List lookup = CollectionFactory.list();
    
    // Indices of attributes in properties file record
    private static final int JIFFLE_NAME = 0;
    private static final int RUNTIME_NAME = 1;
    private static final int PROVIDER = 2;
    private static final int VOLATILE = 3;
    private static final int RETURN = 4;
    private static final int FIRST_ARG = 5;
    
    private static final int MIN_ATTRIBUTES = FIRST_ARG + 1;

    static {
        InputStream in = null;
        try {
            in = FunctionLookup.class.getClassLoader().getResourceAsStream(PROPERTIES_FILE);
            Properties properties = new Properties();
            properties.load(in);
            
            Enumeration names = properties.propertyNames();
            while (names.hasMoreElements()) {
                String name = (String) names.nextElement();
                String value = properties.getProperty(name);

                String[] attr = value.split("[,\\s]+");
                if (attr.length < MIN_ATTRIBUTES) {
                    throw new IllegalArgumentException(
                            "Error reading " + PROPERTIES_FILE + " record: " + name + "=" + value);
                }
                
                FunctionInfo.Provider provider = FunctionInfo.Provider.get( attr[PROVIDER] );
                if (provider == null) {
                    throw new IllegalArgumentException(
                            "Unrecognized Jiffle function provider (" 
                            + attr[PROVIDER] + ") in " + PROPERTIES_FILE);
                }

                boolean isVolatile = Boolean.parseBoolean(attr[VOLATILE]);
                
                final int numArgs = "0".equals(attr[FIRST_ARG]) ? 
                        0 : attr.length - FIRST_ARG;
                
                String[] argTypes = new String[numArgs];
                for (int i = 0, k = FIRST_ARG; i < numArgs; i++, k++) {
                    argTypes[i] = attr[k];
                }

                lookup.add( new FunctionInfo(
                        attr[JIFFLE_NAME], attr[RUNTIME_NAME], 
                        provider, isVolatile, attr[RETURN], argTypes) );
            }

        } catch (Exception ex) {
            throw new IllegalArgumentException("Internal compiler error", ex);

        } finally {
            try {
                if (in != null) in.close();
            } catch (Exception ex) {
                // ignore
            }
        }
    }
    
    /**
     * Checks if a function is defined.
     *
     * @param jiffleName the name of the function used in a Jiffle script
     * @param argTypes argument type names; null or empty for no-arg functions
     *
     * @return {@code true} if defined; {@code false} otherwise
     */
    public static boolean isDefined(String jiffleName, List argTypes) {
        try {
            getInfo(jiffleName, argTypes);
        } catch (UndefinedFunctionException ex) {
            return false;
        }
        
        return true;
    }
    
    /**
     * Gets the info for a function.
     *
     * @param jiffleName the name of the function used in a Jiffle script
     * @param argTypes argument type names; null or empty for no-arg functions
     *
     * @return function info
     * @throws UndefinedFunctionException if {@code jiffleName} is not recognized
     */
    public static FunctionInfo getInfo(String jiffleName, List argTypes)
            throws UndefinedFunctionException {

        for (FunctionInfo info : lookup) {
            if (info.matches(jiffleName, argTypes)) {
                return info;
            }
        }
        
        // should never get here
        throw new UndefinedFunctionException("Unrecognized function: " + jiffleName);
    }
    
    /**
     * Gets the runtime source for the function. This will consist of
     * provider name plus function name in the case of {@code JiffleFunction}
     * and {@code java.lang.Math} methods, or runtime class field name in the
     * case of proxy (image info) functions.
     *
     * @param jiffleName the name of the function used in a Jiffle script
     * @param argTypes argument type names; null or empty for no-arg functions
     *
     * @return the runtime source
     * @throws UndefinedFunctionException if {@code jiffleName} is not recognized
     */
    public static String getRuntimeExpr(String jiffleName, List argTypes)
            throws UndefinedFunctionException {
        
        return getInfo(jiffleName, argTypes).getRuntimeExpr();
    }
    
    /**
     * Searches for a function with a script name that matches {@code jiffleName}
     * and gets its return type. This method relies on the fact that Jiffle 
     * has the same return type for all functions with the same root name.
     * 
     * @param jiffleName name to match
     * @return the return type: D or List
     * 
     * @throws UndefinedFunctionException if the name is not matched 
     */
    public static String getReturnType(String jiffleName) throws UndefinedFunctionException {
        for (FunctionInfo info : lookup) {
            if (info.getJiffleName().equals(jiffleName)) {
                return info.getReturnType();
            }
        }
        
        throw new UndefinedFunctionException(jiffleName);
    }
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy