Package org.openquark.cal.compiler

Source Code of org.openquark.cal.compiler.LocallyDefinedNamesCollector

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* 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.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* 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 OWNER 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.
*/


/*
* BindingTrackingSourceModelTraverser.java
* Creation date: (Feb 14, 2006)
* By: James Wright
*/
package org.openquark.cal.compiler;

import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.openquark.cal.compiler.SourceModel.ArgBindings;
import org.openquark.cal.compiler.SourceModel.FieldPattern;
import org.openquark.cal.compiler.SourceModel.Import;
import org.openquark.cal.compiler.SourceModel.LocalDefn;
import org.openquark.cal.compiler.SourceModel.ModuleDefn;
import org.openquark.cal.compiler.SourceModel.Name;
import org.openquark.cal.compiler.SourceModel.Pattern;
import org.openquark.cal.compiler.SourceModel.SourceElement;
import org.openquark.cal.compiler.SourceModel.Expr.Lambda;
import org.openquark.cal.compiler.SourceModel.Expr.Let;
import org.openquark.cal.compiler.SourceModel.Expr.Case.Alt.UnpackDataCons;
import org.openquark.cal.compiler.SourceModel.Expr.Case.Alt.UnpackListCons;
import org.openquark.cal.compiler.SourceModel.Expr.Case.Alt.UnpackRecord;
import org.openquark.cal.compiler.SourceModel.Expr.Case.Alt.UnpackTuple;
import org.openquark.cal.compiler.SourceModel.FunctionDefn.Algebraic;
import org.openquark.cal.compiler.SourceModel.Import.UsingItem;
import org.openquark.cal.compiler.SourceModel.LocalDefn.Function.Definition;
import org.openquark.cal.util.ArrayStack;


/**
* An implementation of SourceModelTraverser that tracks the current local definitions that
* are in scope.  The current top-level function is considered to be in scope.
*
* @param <R> the return type. If the return value is not used, specify {@link Void}.
*
* @author James Wright
*/
class BindingTrackingSourceModelTraverser<R> extends SourceModelTraverser<Object, R> {

    /**
     * Name of the module currently being processed.
     * This will be set when a ModuleDefn is visited.
     */
    private ModuleName moduleName;
   
    /**
     * ArrayStack of Maps (String -> SourceElement) that map from bindings
     * currently in scope to the corresponding source element.
     */
    private final ArrayStack<Map<String, SourceElement>> currentBindings;

    /**
     * ArrayStacks of Maps (String -> LocalFunctionIdentifier) that map from
     * bindings of local function names currently in scope to the corresponding
     * LocalFunctionIdentifier.
     */
    private final ArrayStack<Map<String, LocalFunctionIdentifier>> currentLocalFunctionIdentifierBindings;
   
    /** Used for generating LocalFunctionIdentifiers when we encounter local functions. */
    private final LocalFunctionIdentifierGenerator localFunctionIdentifierGenerator;
   
    /** Map (String -> QualifiedName) from function names declared in using clauses to the QualifiedName of the entity that they refer to */
    private final Map<String, QualifiedName> usingFunctionNames = new HashMap<String, QualifiedName>();
   
    /** Map (String -> QualifiedName) from datacons names declared in using clauses to the QualifiedName of the entity that they refer to */
    private final Map<String, QualifiedName> usingDataconsNames = new HashMap<String, QualifiedName>();
   
    /** Map (String -> QualifiedName) from typecons names declared in using clauses to the QualifiedName of the entity that they refer to */
    private final Map<String, QualifiedName> usingTypeconsNames = new HashMap<String, QualifiedName>();
   
    /** Map (String -> QualifiedName) from type class names declared in using clauses to the QualifiedName of the entity that they refer to */
    private final Map<String, QualifiedName> usingTypeClassNames = new HashMap<String, QualifiedName>();
   
    BindingTrackingSourceModelTraverser() {
        moduleName = null;
        localFunctionIdentifierGenerator = new LocalFunctionIdentifierGenerator();
        currentBindings = ArrayStack.make();
        currentLocalFunctionIdentifierBindings = ArrayStack.make();
    }

    /** {@inheritDoc} */
    @Override
    public R visit_ModuleDefn(ModuleDefn defn, Object arg) {
        // Save modulename for clients
        moduleName = SourceModel.Name.Module.toModuleName(defn.getModuleName());
        return super.visit_ModuleDefn(defn, arg);
    }
   
    /**
     * {@inheritDoc}
     * This implementation of visitImport passes the name of the imported module
     * to each of its child UsingItems.
     *
     */
    @Override
    public R visit_Import(Import importStmt, Object arg) {
       
        ModuleName importedModuleName = SourceModel.Name.Module.toModuleName(importStmt.getImportedModuleName());
        UsingItem[] usingItems = importStmt.getUsingItems();

        for (final UsingItem usingItem : usingItems) {
            // We pass the name of the imported module to using clause visitors so that
            // they can fill the using maps; we're overriding the default traversal method
            // here, so we don't call the superclass method.
            usingItem.accept(this, importedModuleName);
        }
   
        return null;
    }
   
    /** {@inheritDoc} */
    @Override
    public R visit_Import_UsingItem_Function(UsingItem.Function usingItemFunction, Object arg) {

        if(arg != null && arg instanceof ModuleName) {
            // Fill up the using maps for name resolution
            ModuleName importedModuleName = (ModuleName)arg;
            String[] usingNames = usingItemFunction.getUsingNames();

            for (final String usingName : usingNames) {
                usingFunctionNames.put(usingName, QualifiedName.make(importedModuleName, usingName));
            }
        }

        return super.visit_Import_UsingItem_Function(usingItemFunction, arg);
    }

    /** {@inheritDoc} */
    @Override
    public R visit_Import_UsingItem_DataConstructor(UsingItem.DataConstructor usingItemDataConstructor, Object arg) {

        if(arg != null && arg instanceof ModuleName) {
            // Fill up the using maps for name resolution
            ModuleName importedModuleName = (ModuleName)arg;
            String[] usingNames = usingItemDataConstructor.getUsingNames();

            for (final String usingName : usingNames) {
                usingDataconsNames.put(usingName, QualifiedName.make(importedModuleName, usingName));
            }
        }

        return super.visit_Import_UsingItem_DataConstructor(usingItemDataConstructor, arg);
    }

    /** {@inheritDoc} */
    @Override
    public R visit_Import_UsingItem_TypeConstructor(UsingItem.TypeConstructor usingItemTypeConstructor, Object arg) {

        if(arg != null && arg instanceof ModuleName) {
            // Fill up the using maps for name resolution
            ModuleName importedModuleName = (ModuleName)arg;
            String[] usingNames = usingItemTypeConstructor.getUsingNames();

            for (final String usingName : usingNames) {
                usingTypeconsNames.put(usingName, QualifiedName.make(importedModuleName, usingName));
            }
        }

        return super.visit_Import_UsingItem_TypeConstructor(usingItemTypeConstructor, arg);
    }

    /** {@inheritDoc} */
    @Override
    public R visit_Import_UsingItem_TypeClass(UsingItem.TypeClass usingItemTypeClass, Object arg) {

        if(arg != null && arg instanceof ModuleName) {
            // Fill up the using maps for name resolution
            ModuleName importedModuleName = (ModuleName)arg;
            String[] usingNames = usingItemTypeClass.getUsingNames();

            for (final String usingName : usingNames) {
                usingTypeClassNames.put(usingName, QualifiedName.make(importedModuleName, usingName));
            }
        }

        return super.visit_Import_UsingItem_TypeClass(usingItemTypeClass, arg);
    }
           
    /** {@inheritDoc} */
    @Override
    public R visit_FunctionDefn_Algebraic(Algebraic algebraic, Object arg) {

        enterScope();

        localFunctionIdentifierGenerator.reset(algebraic.getName());

        for(int i = 0; i < algebraic.getNParameters(); i++) {
            SourceModel.Parameter param = algebraic.getNthParameter(i);
            addRegularBinding(param.getName(), param);
        }
       
        R ret = super.visit_FunctionDefn_Algebraic(algebraic, arg);
       
        localFunctionIdentifierGenerator.reset(null);
       
        leaveScope();
        return ret;
    }

    /** {@inheritDoc} */
    @Override
    public R visit_Expr_Lambda(Lambda lambda, Object arg) {

        enterScope();
       
        for(int i = 0; i < lambda.getNParameters(); i++) {
            SourceModel.Parameter param = lambda.getNthParameter(i);
            addRegularBinding(param.getName(), param);
        }

        R ret = super.visit_Expr_Lambda(lambda, arg);
        leaveScope();
        return ret;
    }

    /** {@inheritDoc} */
    @Override
    public R visit_Expr_Let(Let let, Object arg) {
       
        enterScope();
       
        // Let expressions are mutually recursive, so we want to bind the
        // function names before we enter the new scope associated with each local function.
       
        /**
         * Handles the adding of bindings for local definitions (both local functions and local pattern match declarations).
         * This is done by walking the local definitions and adding a binding for each local function / pattern-bound variable
         * encountered. The synthetic local function generated by the compiler for desugaring a local pattern match declaration
         * is also taken into account.
         *
         * @author Joseph Wong
         */
        class LocallyDefinedNamesCollector extends IdentifierResolver.LocalBindingsProcessor<LinkedHashSet<String>, R> {

            /**
             * {@inheritDoc}
             */
            @Override
            void processLocalDefinitionBinding(final String name, final SourceModel.SourceElement localDefinition, final LinkedHashSet<String> arg) {
                addLocalDefinitionBinding(name, localDefinition);
            }
           
            /**
             * {@inheritDoc}
             */
            @Override
            void additionallyProcessPatternVar(final Pattern.Var var, final LinkedHashSet<String> patternVarNames) {
                patternVarNames.add(var.getName());
            }

            /**
             * {@inheritDoc}
             */
            @Override
            void additionallyProcessPunnedTextualRecordFieldPattern(final FieldName.Textual fieldName, final Name.Field fieldNameElement, final LinkedHashSet<String> patternVarNames) {
                patternVarNames.add(fieldName.getCalSourceForm());
            }

            /**
             * {@inheritDoc}
             */
            @Override
            void additionallyProcessPunnedTextualDataConsFieldPattern(final FieldName.Textual fieldName, final Name.Field fieldNameElement, final Name.DataCons dataConsName, final LinkedHashSet<String> patternVarNames) {
                patternVarNames.add(fieldName.getCalSourceForm());
            }
           
            /**
             * Adds an additional binding for the synthetic local function which is generated by the compiler to host the defining
             * expression of a local pattern match declaration. This is done to keep the local function identifier generator in
             * sync with what the compiler would do.
             *
             * @param patternMatchDecl the pattern match declaration.
             * @param patternVarNames the LinkedHashSet of the pattern variable names, in source order.
             */
            private void addBindingForSyntheticLocalDefinition(final LocalDefn.PatternMatch patternMatchDecl, final LinkedHashSet<String> patternVarNames) {
                addLocalDefinitionBinding(FreeVariableFinder.makeTempVarNameForDesugaredLocalPatternMatchDecl(patternVarNames), patternMatchDecl);
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public R visit_LocalDefn_PatternMatch_UnpackDataCons(final LocalDefn.PatternMatch.UnpackDataCons unpackDataCons, final LinkedHashSet<String> arg) {
                // visit only the patterns
                final LinkedHashSet<String> patternVarNames = new LinkedHashSet<String>();
                super.visit_LocalDefn_PatternMatch_UnpackDataCons(unpackDataCons, patternVarNames);
                // add the synthetic definition last
                addBindingForSyntheticLocalDefinition(unpackDataCons, patternVarNames);
                return null;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public R visit_LocalDefn_PatternMatch_UnpackListCons(final LocalDefn.PatternMatch.UnpackListCons unpackListCons, final LinkedHashSet<String> arg) {
                // visit only the patterns
                final LinkedHashSet<String> patternVarNames = new LinkedHashSet<String>();
                super.visit_LocalDefn_PatternMatch_UnpackListCons(unpackListCons, patternVarNames);
                // add the synthetic definition last
                addBindingForSyntheticLocalDefinition(unpackListCons, patternVarNames);
                return null;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public R visit_LocalDefn_PatternMatch_UnpackRecord(final LocalDefn.PatternMatch.UnpackRecord unpackRecord, final LinkedHashSet<String> arg) {
                // visit only the field patterns (and not the base record pattern - since we do not support them in local pattern match decl)
                final LinkedHashSet<String> patternVarNames = new LinkedHashSet<String>();
                super.visit_LocalDefn_PatternMatch_UnpackRecord(unpackRecord, patternVarNames);
                // add the synthetic definition last
                addBindingForSyntheticLocalDefinition(unpackRecord, patternVarNames);
                return null;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public R visit_LocalDefn_PatternMatch_UnpackTuple(final LocalDefn.PatternMatch.UnpackTuple unpackTuple, final LinkedHashSet<String> arg) {
                // visit only the patterns
                final LinkedHashSet<String> patternVarNames = new LinkedHashSet<String>();
                super.visit_LocalDefn_PatternMatch_UnpackTuple(unpackTuple, patternVarNames);
                // add the synthetic definition last
                addBindingForSyntheticLocalDefinition(unpackTuple, patternVarNames);
                return null;
            }
        }
       
        // Use the LocallyDefinedNamesCollector to visit the let definitions
        final LocallyDefinedNamesCollector locallyDefinedNamesCollector = new LocallyDefinedNamesCollector();
        final int nLocalFunctions = let.getNLocalDefinitions();
        for (int i = 0; i < nLocalFunctions; i++) {
            let.getNthLocalDefinition(i).accept(locallyDefinedNamesCollector, null);
        }

        // Now call the superclass implementation to walk through the let expression with the right name bindings
        R ret = super.visit_Expr_Let(let, arg);
        leaveScope();
        return ret;
    }
        
    /** {@inheritDoc} */
    @Override
    public R visit_LocalDefn_Function_Definition(Definition function, Object arg) {

        enterScope();
       
        for(int i = 0; i < function.getNParameters(); i++) {
            SourceModel.Parameter param = function.getNthParameter(i);
            addRegularBinding(param.getName(), param);
        }
       
        R ret = super.visit_LocalDefn_Function_Definition(function, arg);
       
        leaveScope();           
        return ret;
    }

    /** {@inheritDoc} */
    @Override
    public R visit_Expr_Case_Alt_UnpackDataCons(UnpackDataCons cons, Object arg) {
        enterScope();
        handleArgBindings(cons.getArgBindings());
       
        R ret = super.visit_Expr_Case_Alt_UnpackDataCons(cons, arg);
        leaveScope();
        return ret;
    }
   
    /**
     * Adds all of the bindings in argBindings to the current scope.
     *   
     * visitCaseExprUnpackDataConsAlt and visitCaseExprUnpackDataConsGroupAlt both
     * do exactly the same (rather involved) processing on their arg bindings.  This
     * common processing is factored into handleArgBindings.
     *
     * @param argBindings ArgBindings the bindings to process
     */
    private void handleArgBindings(ArgBindings argBindings) {
       
        if(argBindings instanceof ArgBindings.Matching) {
           
            ArgBindings.Matching matchingArgBindings = (ArgBindings.Matching)argBindings;
           
            for (int i = 0; i < matchingArgBindings.getNFieldPatterns(); i++) {
                FieldPattern fieldPattern = matchingArgBindings.getNthFieldPattern(i);
                Pattern pattern = fieldPattern.getPattern();
               
                if (pattern == null) {
                    // punning.
                   
                    // Textual field names become Vars of the same name.
                    // Ordinal field names become wildcards ("_").
                    FieldName fieldName = fieldPattern.getFieldName().getName();
                    if (fieldName instanceof FieldName.Textual) {
                        pattern = Pattern.Var.make(fieldName.getCalSourceForm());
                    }
                }
               
                if (pattern instanceof Pattern.Var) {
                    Pattern.Var patternVar = (Pattern.Var)pattern;
                    addRegularBinding(patternVar.getName(), patternVar);
                }
            }

        } else if (argBindings instanceof ArgBindings.Positional) {
           
            ArgBindings.Positional positionalArgBindings = (ArgBindings.Positional)argBindings;
           
            for (int i = 0; i < positionalArgBindings.getNPatterns(); i++) {
                Pattern pattern = positionalArgBindings.getNthPattern(i);
                if (pattern instanceof Pattern.Var) {
                    Pattern.Var patternVar = (Pattern.Var)pattern;
                    addRegularBinding(patternVar.getName(), patternVar);
                }
            }
        }
    }
   
    /** {@inheritDoc} */
    @Override
    public R visit_Expr_Case_Alt_UnpackListCons(UnpackListCons cons, Object arg) {

        enterScope();
       
        if(cons.getHeadPattern() instanceof Pattern.Var) {
            Pattern.Var patternVar = (Pattern.Var)cons.getHeadPattern();
            addRegularBinding(patternVar.getName(), patternVar);
        }
       
        if(cons.getTailPattern() instanceof Pattern.Var) {
            Pattern.Var patternVar = (Pattern.Var)cons.getTailPattern();
            addRegularBinding(patternVar.getName(), patternVar);
        }
       
        R ret = super.visit_Expr_Case_Alt_UnpackListCons(cons, arg);
        leaveScope();
        return ret;
    }
   
    /** {@inheritDoc} */
    @Override
    public R visit_Expr_Case_Alt_UnpackRecord(UnpackRecord record, Object arg) {

        enterScope();
       
        for(int i = 0; i < record.getNFieldPatterns(); i++) {
            FieldPattern pattern = record.getNthFieldPattern(i);
           
            if(pattern.getPattern() != null &&
               pattern.getPattern() instanceof Pattern.Var) {
                Pattern.Var patternVar = (Pattern.Var)pattern.getPattern();
                addRegularBinding(patternVar.getName(), patternVar);

            } else if (pattern.getPattern() == null) {
                addRegularBinding(pattern.getFieldName().getName().getCalSourceForm(), pattern);
            }
        }
       
        if(record.getBaseRecordPattern() != null) {
            if(record.getBaseRecordPattern() instanceof Pattern.Var) {
                Pattern.Var patternVar = (Pattern.Var)record.getBaseRecordPattern();
                addRegularBinding(patternVar.getName(), patternVar);
            }
        }
       
        R ret = super.visit_Expr_Case_Alt_UnpackRecord(record, arg);
        leaveScope();
        return ret;
    }

    /** {@inheritDoc} */
    @Override
    public R visit_Expr_Case_Alt_UnpackTuple(UnpackTuple tuple, Object arg) {

        enterScope();
       
        for(int i = 0; i < tuple.getNPatterns(); i++) {
            Pattern pattern = tuple.getNthPattern(i);
            if(pattern instanceof Pattern.Var) {
                Pattern.Var patternVar = (Pattern.Var)pattern;
                addRegularBinding(patternVar.getName(), patternVar);
            }
        }
       
        R ret = super.visit_Expr_Case_Alt_UnpackTuple(tuple, arg);
        leaveScope();
        return ret;
    }

    /**
     * Adds a binding to the current innermost scope
     * @param name Name of the binding to add
     * @param sourceElement SourceElement that name should be bound to
     */
    private void addRegularBinding(String name, SourceModel.SourceElement sourceElement) {
        Map<String, SourceElement> currentScope = currentBindings.peek();
        currentScope.put(name, sourceElement);
    }
   
    /**
     * Adds a binding to the current innermost scope and records the unique identifier for
     * a local definition (a function or a pattern variable in a pattern match declaration).
     * @param name String name of the local definition to add a binding for
     * @param localDefinition SourceModel for the local function
     */
    private void addLocalDefinitionBinding(String name, SourceModel.SourceElement localDefinition) {
        addRegularBinding(name, localDefinition);

        Map<String, LocalFunctionIdentifier> currentIdentifierScope = currentLocalFunctionIdentifierBindings.peek();

        // Don't try to track local function identifiers without a module name and toplevel function
        if(moduleName != null && getCurrentFunction() != null) {
            LocalFunctionIdentifier localFunctionIdentifier = localFunctionIdentifierGenerator.generateLocalFunctionIdentifier(moduleName, name);
            currentIdentifierScope.put(name, localFunctionIdentifier);
        }
    }
   
    /**
     * Adds a new scope to the current bindings.
     */
    private void enterScope() {
        currentBindings.push(new HashMap<String, SourceElement>());
        currentLocalFunctionIdentifierBindings.push(new HashMap<String, LocalFunctionIdentifier>());
    }
   
    /**
     * Removes the current scope from the bindings.
     */
    private void leaveScope() {
        currentBindings.pop();
        currentLocalFunctionIdentifierBindings.pop();
    }
   
    /** @return The name of the currently in-scope function, if any */
    String getCurrentFunction() {
        return localFunctionIdentifierGenerator.getCurrentFunction();
    }
   
    /** @return The name of the module being processed */
    ModuleName getModuleName() {
        return moduleName;
    }
   
    /**
     * @param name Name to fetch the qualifiedName for
     * @param moduleNameResolver the module name resolver to use for resolving module names.
     * @return QualifiedName of the top-level entity that name refers to, or null if name does not refer to
     *          a top-level entity.
     */
    QualifiedName getQualifiedName(Name.Qualifiable name, ModuleNameResolver moduleNameResolver) {

        String unqualifiedName = name.getUnqualifiedName();
        if(name.getModuleName() != null) {
            ModuleNameResolver.ResolutionResult resolution = moduleNameResolver.resolve(SourceModel.Name.Module.toModuleName(name.getModuleName()));
            ModuleName resolvedModuleName = resolution.getResolvedModuleName();
            return QualifiedName.make(resolvedModuleName, name.getUnqualifiedName());
        }
       
        if(isBound(unqualifiedName)) {
            return null;
        }
       
        if(name instanceof Name.Function && usingFunctionNames.containsKey(unqualifiedName)) {
            return usingFunctionNames.get(unqualifiedName);
        }
       
        if(name instanceof Name.DataCons && usingDataconsNames.containsKey(unqualifiedName)) {
            return usingDataconsNames.get(unqualifiedName);
        }
       
        if(name instanceof Name.TypeCons && usingTypeconsNames.containsKey(unqualifiedName)) {
            return usingTypeconsNames.get(unqualifiedName);
        }
       
        if(name instanceof Name.TypeClass && usingTypeClassNames.containsKey(unqualifiedName)) {
            return usingTypeClassNames.get(unqualifiedName);
        }
       
        if(name instanceof Name.WithoutContextCons) {
            if(usingDataconsNames.containsKey(unqualifiedName)) {
                return usingDataconsNames.get(unqualifiedName);
            }
           
            if(usingTypeconsNames.containsKey(unqualifiedName)) {
                return usingTypeconsNames.get(unqualifiedName);
            }
           
            if(usingTypeClassNames.containsKey(unqualifiedName)) {
                return usingTypeClassNames.get(unqualifiedName);
            }
        }
       
        return QualifiedName.make(getModuleName(), unqualifiedName);
    }
   
    /** @return A clone of the LocalFunctionIdentifierGenerator */
    LocalFunctionIdentifierGenerator getLocalFunctionNameGenerator() {
        return localFunctionIdentifierGenerator.clone();
    }
   
    /**
     * @return True if name is currently bound, or false otherwise.
     * @param name String name to check
     */
    boolean isBound(String name) {
       
        for(int i = 0, nBindings = currentBindings.size(); i < nBindings; i++) {
            Map<String, SourceElement> currentScope = currentBindings.peek(i);
            if(currentScope.containsKey(name)) {
                return true;
            }
        }
        return false;
    }
   
    /**
     * @param name Name of binding to retrieve the defining SourceElement for
     * @return The SourceElement that defines the current binding specified by
     *          name, or null if name is not currently bound.
     */
    SourceModel.SourceElement getBoundElement(String name) {
       
        for(int i = 0, nBindings = currentBindings.size(); i < nBindings; i++) {
            Map<String, SourceElement> currentScope = currentBindings.peek(i);
            Object sourceElement = currentScope.get(name);
            if(sourceElement != null) {
                return (SourceModel.SourceElement)sourceElement;
            }
        }
       
        return null;
    }

    /**
     * @param name Name of a local function definition that is current in scope
     * @return The LocalFunctionIdentifier that corresponds to the current binding of name,
     *          or null if name is not currently bound to a local function.
     */
    LocalFunctionIdentifier getBoundLocalFunctionIdentifier(String name) {
        for(int i = 0, nBindings = currentBindings.size(); i < nBindings; i++) {
            Map<String, SourceElement> currentScope = currentBindings.peek(i);
            SourceElement sourceElement = currentScope.get(name);
           
            if(sourceElement == null) {
                continue;
            }
           
            if(!(sourceElement instanceof LocalDefn.Function || sourceElement instanceof Pattern.Var || sourceElement instanceof FieldPattern)) {
                return null;
            }
           
            Map<String, LocalFunctionIdentifier> currentIdentifierScope = currentLocalFunctionIdentifierBindings.peek(i);
            return currentIdentifierScope.get(name);
        }
       
        return null;
    }
}
TOP

Related Classes of org.openquark.cal.compiler.LocallyDefinedNamesCollector

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.